Не секрет, что C# сегодня популярный и динамично развывающийся язык, в отличие от своего прямого конкурента — языка Java, который в плане функциональности переживает период застоя. Основное неоспоримое преимущество Java — настоящая кросплатформенность, а не унылая и ограниченная, как у C#. C# — простой язык, благодаря простоте живёт и PHP. Но в то же время он весьма функциональный, и имеет статус «гибридного» языка, совмещая в себе различные парадигмы, встроенную поддержку как императивного стиля программирования, так и функционального. Как и любой язык, шарп имеет свои тонкости, особенности, «подводные камни» и малоизвестные возможности. Что я имею ввиду? Читайте под катом…Упаковка и распаковка — знают все, да не каждыйСсылочные типы (object, dynamic, string, class, interface, delegate) хранятся в управляемой куче, типы значений (struct, enum; bool, byte, char, int, float, double) — в стеке приложения (кроме случая, когда тип значения является полем класса). Преобразование типа значений к ссылочному типу сопровождается неявной операцией упаковки (boxing) — помещение копии типа значений в класс-обёртку, экземпляр которого сохраняется в куче. Упаковочный тип генерируется CLR и реализует интерфейсы сохраняемого типа значения. Преобразование ссылочного типа к типу значений вызывает операцию распаковки (unboxing) — извлечение из упаковки копии типа значения и помещение её в стек.
using System;class Program
{
static void Main()
{
int val = 5;
object obj = val; // присваивание сопровождается упаковкой
int valUnboxed = (int)obj; // приведение вызовет распаковку
}
}Соответствующий IL-код:.locals init ([0] int32 val, [1] object obj, [2] int32 valUnboxed)
IL_0000: nop
IL_0001: ldc.i4.5
IL_0002: stloc.0
IL_0003: ldloc.0
IL_0004: box [mscorlib]System.Int32
IL_0009: stloc.1
IL_000a: ldloc.1
IL_000b: unbox.any [mscorlib]System.Int32
IL_0010: stloc.2
IL_0011: retУпаковка и распаковка являются относительно медленными операциями (подразумевают копирование), поэтому по возможности следует их избегать. Нижеследующий код отображает неочевидные случаи, приводящие к упаковке:
using System;class Program
{
static void Main()
{
// 1. Преобразование типа значений в ссылку на реализуемый им интерфейс
IComparable<int> iComp = 1;
// 2. Преобразование типа enum в ссылку на System.Enum
Enum format = UriFormat.Unescaped;
// 3. Преобразование типа значений к типу dynamic
dynamic d = 1;
}
}В msdn рекомендуется избегать типов значений в случаях, когда они должны быть упакованы много раз, например в не универсальных классах коллекций (ArrayList). Упаковки-преобразования типов значений можно избежать с помощью универсальных коллекций (System.Collections.Generic namespace). Также следует помнить, что dynamic на уровне IL-кода — это тот же object, только (не всегда) помеченный атрибутами. Рекурсия в лямбдах — о зловредном замыканииОбратимся к классической реализации рекурсивного вычисления факториала при помощи лямбда-выражений:using System;
using System.Numerics;class Program
{
static void Main()
{
Func<int, BigInteger> fact = null;
fact = x => x > 1 ? x * fact(x - 1) : 1;Read more: Habrahabr.ru
using System;class Program
{
static void Main()
{
int val = 5;
object obj = val; // присваивание сопровождается упаковкой
int valUnboxed = (int)obj; // приведение вызовет распаковку
}
}Соответствующий IL-код:.locals init ([0] int32 val, [1] object obj, [2] int32 valUnboxed)
IL_0000: nop
IL_0001: ldc.i4.5
IL_0002: stloc.0
IL_0003: ldloc.0
IL_0004: box [mscorlib]System.Int32
IL_0009: stloc.1
IL_000a: ldloc.1
IL_000b: unbox.any [mscorlib]System.Int32
IL_0010: stloc.2
IL_0011: retУпаковка и распаковка являются относительно медленными операциями (подразумевают копирование), поэтому по возможности следует их избегать. Нижеследующий код отображает неочевидные случаи, приводящие к упаковке:
using System;class Program
{
static void Main()
{
// 1. Преобразование типа значений в ссылку на реализуемый им интерфейс
IComparable<int> iComp = 1;
// 2. Преобразование типа enum в ссылку на System.Enum
Enum format = UriFormat.Unescaped;
// 3. Преобразование типа значений к типу dynamic
dynamic d = 1;
}
}В msdn рекомендуется избегать типов значений в случаях, когда они должны быть упакованы много раз, например в не универсальных классах коллекций (ArrayList). Упаковки-преобразования типов значений можно избежать с помощью универсальных коллекций (System.Collections.Generic namespace). Также следует помнить, что dynamic на уровне IL-кода — это тот же object, только (не всегда) помеченный атрибутами. Рекурсия в лямбдах — о зловредном замыканииОбратимся к классической реализации рекурсивного вычисления факториала при помощи лямбда-выражений:using System;
using System.Numerics;class Program
{
static void Main()
{
Func<int, BigInteger> fact = null;
fact = x => x > 1 ? x * fact(x - 1) : 1;Read more: Habrahabr.ru
0 comments:
Post a Comment