SlideShare a Scribd company logo
1 of 39
Deep Dive
Сергей Тепляков, Visual C# MVP
.NET Architect at Luxoft
SergeyTeplyakov.blogspot.com
А насколько глубоко будем
нырять?
Настолько глубоко?
class X { public const int Value = 1000; }
static int Foo(Func<int?, byte> x, object y) { return 1; }
static int Foo(Func<X, byte> x, string y) { return 2; }
var a = Foo(X => (byte)X.Value, null);
unchecked
{
Console.WriteLine(a);
}
unchecked
{
var a = Foo(X => (byte)X.Value, null);
Console.WriteLine(a);
}
unchecked
{
var a = Foo(X => (byte)X.Value, (object)null);
Console.WriteLine(a);
} Увидим 1Увидим 2Снова 1!!!!
Нет! Нет! Нет!
• Подробнее об этом треше -
http://rsdn.ru/forum/dotnet/3272728.flat
• См. этюды nikov-а на rsdn.ru –
http://rsdn.ru/Forum/?fuid=55905
• Кури “The C# Programming Language” by Hejlsberg et al!
Что нужно для работы цикла
foreach?
• IEnumerable?
• IEnumerable of T?
• Что-то еще?
• Нужен метод GetEnumerator, возвращающий
объект с методом MoveNext и свойством
Current!
В F# пошли еще дальше…
• Поддержку цикла for можно добавить с помощью методов
расширения!
type Int32 with
// Получаем список квадратов чисел от 1 до текущего значения
member x.GetEnumerator() =
({1..x} |> Seq.map(fun x -> x*x)).GetEnumerator()
// Выводит 1 4 9 16 25
for n in 5 do printf "%d " n
Утиная типизация
Если кто-то ходит, как утка, и крякает, как
утка, то это и есть может быть утка индюшка
с утиным адаптером...
«Утиная типизация» в C#
• foreach
• Требуется GetEnumerator, MoveNext и свойство Current
• http://sergeyteplyakov.blogspot.com/2012/08/duck-typing-
foreach.html
• LINQ (Query Comprehension syntax)
• Требуются методы Select, Where, GroupBy etc.
• Collection initializer
• Требуется метод Add
• C# 5.0 Async Features
• Требуются GetAwaiter() и методы BeginAwait(Action) и
EndAwait(), GetResult() и свойства IsCompleted.
• System.Runtime.CompilerServices.ExtensionAttribute
• Методы расширения завязаны не на конкретный тип
атрибутов!
Блоки итераторов…
public static IEnumerable<string> ReadByLine(string path)
{
if (string.IsNullOrEmpty(path))
throw new ArgumentNullException("path");
using (var sr = new StreamReader(path))
{
string s;
while ((s = sr.ReadLine()) != null)
yield return s;
}
}
var seq = ReadByLine(null); // 1
var s = seq.Select(line => line.Length); // 2
Console.WriteLine(s.Max()); // 3
Все ли нормально с
кодом?
Этот же подход
используется и для
асинхронных методов!
Когда получим
исключение?
Код до первого yield
return вызовется при
первом вызове метода
MoveNext!
Какое исключение получим?
class Foo
{
public Foo() { throw new Exception("Ooops!!"); }
}
static T Create<T>() where T : new()
{
var instance = new T();
// Write to log some message
return instance;
}
var f = Create<Foo>();
Какое исключение
получим?
Почему?
• Используется reflection (Activator.CreateInstance).
• Все обобщения должны содержать одну реализацию!
• Вызов метода через Reflection всегда «оборачивает»
исходное исключение в TargetInvocationException
• «Все нетривиальные абстракции текут»
Джоэл Спольски
Повторная генерация
исключений
• Делаем "правильную" фабрику. Наивная реализация:
public static T CreateInstanceNaive<T>() where T : new()
{
try
{
return new T();
}
catch (TargetInvocationException e)
{
// Исходный стек вызовов потерян, теперь все
// будут думать, что виноваты мы!
throw e.InnerException;
}
}
Используем ExceptionDispatchInfo
public static T CreateInstance<T>() where T : new()
{
try
{
return new T();
}
catch(TargetInvocationException e)
{
ExceptionDispatchInfo di =
ExceptionDispatchInfo.Capture(e.InnerException);
di.Throw();
// компилятор C# не знает, что эта точка недостижима
return default(T);
}
}
Quiz #3. Исключение в блоке
finally
public static void FinallyThatThrows()
{
try {
throw new Exception("1");
}
catch(Exception e) {
throw new Exception("2");
}
finally {
throw new Exception("3");
}
}
try { FinallyThatThrows(); }
catch(Exception e) {
Console.WriteLine(e.Message);
}
Что получим? "1", "2"
или "3"?
Quiz # 4. Маскирование
исключений в блоке using
class CustomDisposable : IDisposable
{
public void Dispose()
{
throw new InvalidOperationException("Ooops!!");
}
}
// Какое исключение перехватывать?
using (var disposable = new CustomDisposable())
{
throw new FileNotFoundException();
}
Подходы к потерянным
исключениям
• C# - побеждает исключение из finally. Исходное теряем
• С++
• Исключение в деструкторе – UB ;)
• std::unexpected, если деструктор вызван при раскрутке стека
• Java
• Исключение в блоке try-finally
• Тоже самое, что и в C#
• try-with-resources
• Побеждает исключение из finally, но исходное остается в скрытых
исключениях
Quiz #6. Создание объекта
class Base : IDisposable
{
public Base()
{
// Выделяем ресурсы!
}
public void Dispose()
{
Console.WriteLine("Base.Dispose");
}
}
class Derived : Base
{
public Derived(object data)
{
if (data == null)
throw new ArgumentNullException("data");
// Oops!!!
}
}
Что будет в этом
случае?
Обработка ошибок…
public static IEnumerable<string> ReadByLine(string path)
{
if (string.IsNullOrEmpty(path))
throw new ArgumentNullException("path");
using (var sr = new StreamReader(path))
{
string s;
while ((s = sr.ReadLine()) != null)
yield return s;
}
}
var seq = ReadByLine(null); // 1
var s = seq.Select(line => line.Length); // 2
Console.WriteLine(s.Max()); // 3
Все ли нормально с
кодом?
Этот же подход
используется и для
асинхронных методов!
Когда получим
исключение?
Код до первого yield
return вызовется при
первом вызове метода
MoveNext!
Корректная реализация
public static IEnumerable<string> ReadByLine(string path)
{
if (string.IsNullOrEmpty(path))
throw new ArgumentNullException("path");
return ReadByLineImpl(path);
}
private static IEnumerable<string> ReadByLineImpl(string path)
{
using (var sr = new StreamReader(path))
{
string s;
while ((s = sr.ReadLine()) != null)
yield return s;
}
}
Наличие блока итераторов
принципиально изменяет
реализацию метода!
var seq = ReadByLine(null); // 1
var s = seq.Select(line => line.Length); // 2
Console.WriteLine(s.Max()); // 3
В чем разница?
• Исключение при вызове метода – ошибка в вызывающем
коде
• Исключение во время перебора элементов –
ошибка/проблема в вызываемом коде!
Необязательные аргументы
и полиморфизм
class Base {
public virtual void Foo(int i = 42) {
Console.WriteLine("Base.Foo: i = {0}", i);
}
}
class Derived : Base {
public override void Foo(int i = 0) {
Console.WriteLine("Derived.Foo: i = {0}", i);
}
}
void Main() {
Derived d = new Derived();
Base b = d;
b.Foo();
d.Foo();
}
Вызываем через
Base!Вызываем через
Derived!
Что будет в этом случае?
// 1
void WithDateTime(DateTime dt = DateTime.Now) { }
// 2
void WithStringEmpty(string s = String.Empty) { }
// 3
void WithEmptyString(string s = "") { }
// 4
void WithMethodCall(int id = GetInvalidId()) { }
static int GetInvalidId() { return -1; }
Примерная реализация
// Декларация
void WithEmptyString(string s = "") { }
// Вызов
WithEmptyString();
// Декларация
[Optional, DefaultParameterValue(value: "")]
static void WithEmptyString(string s) {}
// Вызов
string defaultValue = GetDefaultValueFromMetadata();
WithEmptyString(defaultValue);
Можно ли изменить
неизменяемое?
(или как можно изменить
readonly поля?)
Вот пример!
• Как поменять C1.X?
class C1 { public readonly int X = 42; }
• Рефлекшн. Но это скушно!
class C2 { public int X; }
[StructLayout(LayoutKind.Explicit)]
class C1Modifier
{
[FieldOffset(0)] public C1 C1;
[FieldOffset(0)] public C2 C2;
}
var c1 = new C1(); // c1.X == 42
// Можификация одного поля приводит к модификации другого!
var c1Modifier = new C1Modifier {C1 = c1};
c1Modifier.C2.X = -1;
// c1.X == -1
Console.WriteLine(c1.X);
Создаем класс с таким же
«расположением»
Создаем «объединение»
(union) из двух таких
классов
Ковариантность массивов
• Что такое ковариантность массивов?
• Вот пример:
object[] o = new string[]{"s1", "s2", "s3"};
• Что в этом опасного?
o[0] = new StringBuilder();
• Это требует проверки типа аргумента во время
исполнения!
• Почему?
• Так было в Java!!
ArrayTypeMismatchException!
Как устроен массив внутри?
Внутреннее устройство массива
Flags, ...
Length (4)
42 (Element 0)
41 (Element 1)
40 (Element 2)
39 (Element 3)
arr[0]
var arr = new int[] {42, 41, 40, 39};
Flags, ...
Length (4)
Type Indentifier
(System.String)
1 (Element 0)
2 (Element 1)
3 (Element 2)
4 (Element 3)
arr[0]
var arr = new string[] {"1", "2", "3", "4"};
Изменяем размер массива
[StructLayout(LayoutKind.Explicit)]
class RefArrayLayout
{
[FieldOffset(0)]
public int Length;
}
[StructLayout(LayoutKind.Explicit)]
class ArrayExplorer
{
[FieldOffset(0)]
public object[] Array;
[FieldOffset(0)]
public RefArrayLayout Layout;
}
var array = new string[] {"1", "2"};
// array.Length = 2
var ae = new ArrayExplorer {Array = array};
ae.Layout.Length = 42;
// Получаем 42
Console.WriteLine(array.Length);
Значимые типы (Value Types)
• В чем главная разница между значимыми и ссылочными
типами?
The most relevant fact about value types is not the
implementation detail of how they are allocated, but rather
the by-design semantic meaning of “value type”, namely that
they are always copied “by value”
Eric Lippert
Метод GetHashCode
• Нужно ли переопределять у структур метод GetHashCode?
• Какова реализация этого метода по умолчанию?
• Корректна ли она?
Пример встроенного метода
GetHashCode
public struct KeyValuePair<TKey, TValue>
{
public TKey Key;
public TValue Value;
}
public struct KeyValuePair
{
public static KeyValuePair<TKey, TValue> Create<TKey, TValue>(
TKey key, TValue value)
{
return new KeyValuePair<TKey, TValue>()
{
Key = key,
Value = value
};
}
}
Используем
реализацию Equals и
GetHashCode по
умолчанию
Тонкости реализации
• KeyValuePair<int, string>:
var kvp1 = KeyValuePair.Create(42, "Foo");
var kvp2 = KeyValuePair.Create(42, "Boo");
Console.WriteLine(kvp1.GetHashCode() == kvp2.GetHashCode());
Console.WriteLine(kvp1.Equals(kvp2));
• KeyValuePair<int, int>:
var kvp1 = KeyValuePair.Create(42, 42);
var kvp2 = KeyValuePair.Create(42, 43);
Console.WriteLine(kvp1.GetHashCode() == kvp2.GetHashCode());
Console.WriteLine(kvp1.Equals(kvp2));
• Одинаковый ли хэш-коды?
• Равны ли объекты?
Тонкости реализации (2)
• ValueType.GetHashCode() содержит две реализации:
• Быструю и точную:
• Структура не содержит «пробелов» в содержимом структуры и
ссылочных типов.
• Используется бинарное представление всего содержимого
структуры.
• Быструю и неточную:
• Структура содержит «пробелов» в содержимом или ссылочные
типы.
• Используется лишь первое поле структуры.
• Подробнее – Why is ValueType.GetHashCode() implemented
like it is?
Нееееттт!!!!1111
Вопросы?
Чего еще почитать?
• Programming Stuff
• C# Tips and Tricks
• Chris Burrows’ Blog
• Eric Lippert’s Blog
• Joe Duffy’s Weblog
• B# .NET BLOG
More C# Deep Dive on
Programming Stuff
• this == null?
• Замыкания в языке C#
• Перегрузка и наследование
• Структуры и конструкторы по умолчанию
• О вреде изменяемых значимых типов.
• Часть 1
• Часть 2
• MVP Summit. День 0. Кэширование делегатов
• MVP Summit. День 1. Об эффективности
Спасибо за внимание
• Сергей Тепляков, Visual C# MVP
• .NET Architect at Luxoft
• Sergey.Teplyakov@gmail.com
• http://sergeyteplyakov.blogspot.com/

More Related Content

What's hot

Павел Довгалюк, Обратная отладка
Павел Довгалюк, Обратная отладкаПавел Довгалюк, Обратная отладка
Павел Довгалюк, Обратная отладкаSergey Platonov
 
Сергей Шамбир, Адаптация Promise/A+ для взаимодействия между C++ и Javascript
Сергей Шамбир, Адаптация Promise/A+ для взаимодействия между C++ и JavascriptСергей Шамбир, Адаптация Promise/A+ для взаимодействия между C++ и Javascript
Сергей Шамбир, Адаптация Promise/A+ для взаимодействия между C++ и JavascriptSergey Platonov
 
Антон Полухин, Немного о Boost
Антон Полухин, Немного о BoostАнтон Полухин, Немного о Boost
Антон Полухин, Немного о BoostSergey Platonov
 
Алексей Куканов — Параллелизм в C++: управляйте приложением, а не потоками!
Алексей Куканов — Параллелизм в C++: управляйте приложением, а не потоками!Алексей Куканов — Параллелизм в C++: управляйте приложением, а не потоками!
Алексей Куканов — Параллелизм в C++: управляйте приложением, а не потоками!Yandex
 
Григорий Демченко, Асинхронность и неблокирующая синхронизация
Григорий Демченко, Асинхронность и неблокирующая синхронизацияГригорий Демченко, Асинхронность и неблокирующая синхронизация
Григорий Демченко, Асинхронность и неблокирующая синхронизацияSergey Platonov
 
Евгений Рыжков, Андрей Карпов Как потратить 10 лет на разработку анализатора ...
Евгений Рыжков, Андрей Карпов Как потратить 10 лет на разработку анализатора ...Евгений Рыжков, Андрей Карпов Как потратить 10 лет на разработку анализатора ...
Евгений Рыжков, Андрей Карпов Как потратить 10 лет на разработку анализатора ...Platonov Sergey
 
Лекция 8: Многопоточное программирование: Intel Threading Building Blocks
Лекция 8: Многопоточное программирование: Intel Threading Building BlocksЛекция 8: Многопоточное программирование: Intel Threading Building Blocks
Лекция 8: Многопоточное программирование: Intel Threading Building BlocksMikhail Kurnosov
 
Объектно-ориентированное программирование. Лекция 5 и 6
Объектно-ориентированное программирование. Лекция 5 и 6Объектно-ориентированное программирование. Лекция 5 и 6
Объектно-ориентированное программирование. Лекция 5 и 6Dima Dzuba
 
Павел Беликов, Как избежать ошибок, используя современный C++
Павел Беликов, Как избежать ошибок, используя современный C++Павел Беликов, Как избежать ошибок, используя современный C++
Павел Беликов, Как избежать ошибок, используя современный C++Sergey Platonov
 
C++ CoreHard Autumn 2018. Полезный constexpr - Антон Полухин
C++ CoreHard Autumn 2018. Полезный constexpr - Антон ПолухинC++ CoreHard Autumn 2018. Полезный constexpr - Антон Полухин
C++ CoreHard Autumn 2018. Полезный constexpr - Антон Полухинcorehard_by
 
RDSDataSource: Чистые тесты на Swift
RDSDataSource: Чистые тесты на SwiftRDSDataSource: Чистые тесты на Swift
RDSDataSource: Чистые тесты на SwiftRAMBLER&Co
 
ПВТ - осень 2014 - Лекция 5 - Многопоточное программирование в языке С++. Р...
ПВТ - осень 2014 - Лекция 5 - Многопоточное программирование в языке С++.   Р...ПВТ - осень 2014 - Лекция 5 - Многопоточное программирование в языке С++.   Р...
ПВТ - осень 2014 - Лекция 5 - Многопоточное программирование в языке С++. Р...Alexey Paznikov
 
ПВТ - весна 2015 - Лекция 3. Реентерабельность. Сигналы. Локальные данные пот...
ПВТ - весна 2015 - Лекция 3. Реентерабельность. Сигналы. Локальные данные пот...ПВТ - весна 2015 - Лекция 3. Реентерабельность. Сигналы. Локальные данные пот...
ПВТ - весна 2015 - Лекция 3. Реентерабельность. Сигналы. Локальные данные пот...Alexey Paznikov
 
Александр Тарасенко, Использование python для автоматизации отладки С/C++ код...
Александр Тарасенко, Использование python для автоматизации отладки С/C++ код...Александр Тарасенко, Использование python для автоматизации отладки С/C++ код...
Александр Тарасенко, Использование python для автоматизации отладки С/C++ код...Sergey Platonov
 
ПВТ - осень 2014 - Лекция 6 - Атомарные операции. Внеочередное выполнение инс...
ПВТ - осень 2014 - Лекция 6 - Атомарные операции. Внеочередное выполнение инс...ПВТ - осень 2014 - Лекция 6 - Атомарные операции. Внеочередное выполнение инс...
ПВТ - осень 2014 - Лекция 6 - Атомарные операции. Внеочередное выполнение инс...Alexey Paznikov
 
DI в C++ тонкости и нюансы
DI в C++ тонкости и нюансыDI в C++ тонкости и нюансы
DI в C++ тонкости и нюансыPlatonov Sergey
 

What's hot (20)

Павел Довгалюк, Обратная отладка
Павел Довгалюк, Обратная отладкаПавел Довгалюк, Обратная отладка
Павел Довгалюк, Обратная отладка
 
Сергей Шамбир, Адаптация Promise/A+ для взаимодействия между C++ и Javascript
Сергей Шамбир, Адаптация Promise/A+ для взаимодействия между C++ и JavascriptСергей Шамбир, Адаптация Promise/A+ для взаимодействия между C++ и Javascript
Сергей Шамбир, Адаптация Promise/A+ для взаимодействия между C++ и Javascript
 
Антон Полухин, Немного о Boost
Антон Полухин, Немного о BoostАнтон Полухин, Немного о Boost
Антон Полухин, Немного о Boost
 
Алексей Куканов — Параллелизм в C++: управляйте приложением, а не потоками!
Алексей Куканов — Параллелизм в C++: управляйте приложением, а не потоками!Алексей Куканов — Параллелизм в C++: управляйте приложением, а не потоками!
Алексей Куканов — Параллелизм в C++: управляйте приложением, а не потоками!
 
Zagursky
ZagurskyZagursky
Zagursky
 
Григорий Демченко, Асинхронность и неблокирующая синхронизация
Григорий Демченко, Асинхронность и неблокирующая синхронизацияГригорий Демченко, Асинхронность и неблокирующая синхронизация
Григорий Демченко, Асинхронность и неблокирующая синхронизация
 
Евгений Рыжков, Андрей Карпов Как потратить 10 лет на разработку анализатора ...
Евгений Рыжков, Андрей Карпов Как потратить 10 лет на разработку анализатора ...Евгений Рыжков, Андрей Карпов Как потратить 10 лет на разработку анализатора ...
Евгений Рыжков, Андрей Карпов Как потратить 10 лет на разработку анализатора ...
 
Лекция 8: Многопоточное программирование: Intel Threading Building Blocks
Лекция 8: Многопоточное программирование: Intel Threading Building BlocksЛекция 8: Многопоточное программирование: Intel Threading Building Blocks
Лекция 8: Многопоточное программирование: Intel Threading Building Blocks
 
C sharp deep dive
C sharp deep diveC sharp deep dive
C sharp deep dive
 
Объектно-ориентированное программирование. Лекция 5 и 6
Объектно-ориентированное программирование. Лекция 5 и 6Объектно-ориентированное программирование. Лекция 5 и 6
Объектно-ориентированное программирование. Лекция 5 и 6
 
Павел Беликов, Как избежать ошибок, используя современный C++
Павел Беликов, Как избежать ошибок, используя современный C++Павел Беликов, Как избежать ошибок, используя современный C++
Павел Беликов, Как избежать ошибок, используя современный C++
 
C++ CoreHard Autumn 2018. Полезный constexpr - Антон Полухин
C++ CoreHard Autumn 2018. Полезный constexpr - Антон ПолухинC++ CoreHard Autumn 2018. Полезный constexpr - Антон Полухин
C++ CoreHard Autumn 2018. Полезный constexpr - Антон Полухин
 
Java 8 puzzlers
Java 8 puzzlersJava 8 puzzlers
Java 8 puzzlers
 
RDSDataSource: Чистые тесты на Swift
RDSDataSource: Чистые тесты на SwiftRDSDataSource: Чистые тесты на Swift
RDSDataSource: Чистые тесты на Swift
 
ПВТ - осень 2014 - Лекция 5 - Многопоточное программирование в языке С++. Р...
ПВТ - осень 2014 - Лекция 5 - Многопоточное программирование в языке С++.   Р...ПВТ - осень 2014 - Лекция 5 - Многопоточное программирование в языке С++.   Р...
ПВТ - осень 2014 - Лекция 5 - Многопоточное программирование в языке С++. Р...
 
ПВТ - весна 2015 - Лекция 3. Реентерабельность. Сигналы. Локальные данные пот...
ПВТ - весна 2015 - Лекция 3. Реентерабельность. Сигналы. Локальные данные пот...ПВТ - весна 2015 - Лекция 3. Реентерабельность. Сигналы. Локальные данные пот...
ПВТ - весна 2015 - Лекция 3. Реентерабельность. Сигналы. Локальные данные пот...
 
Александр Тарасенко, Использование python для автоматизации отладки С/C++ код...
Александр Тарасенко, Использование python для автоматизации отладки С/C++ код...Александр Тарасенко, Использование python для автоматизации отладки С/C++ код...
Александр Тарасенко, Использование python для автоматизации отладки С/C++ код...
 
JRebel
JRebelJRebel
JRebel
 
ПВТ - осень 2014 - Лекция 6 - Атомарные операции. Внеочередное выполнение инс...
ПВТ - осень 2014 - Лекция 6 - Атомарные операции. Внеочередное выполнение инс...ПВТ - осень 2014 - Лекция 6 - Атомарные операции. Внеочередное выполнение инс...
ПВТ - осень 2014 - Лекция 6 - Атомарные операции. Внеочередное выполнение инс...
 
DI в C++ тонкости и нюансы
DI в C++ тонкости и нюансыDI в C++ тонкости и нюансы
DI в C++ тонкости и нюансы
 

Viewers also liked

WinDbg в руках .NET разработчика
WinDbg в руках .NET разработчикаWinDbg в руках .NET разработчика
WinDbg в руках .NET разработчикаMikhail Shcherbakov
 
Void safety on Kiev ALT.NET
Void safety on Kiev ALT.NETVoid safety on Kiev ALT.NET
Void safety on Kiev ALT.NETSergey Teplyakov
 
Тонкости асинхронного программирования
Тонкости асинхронного программированияТонкости асинхронного программирования
Тонкости асинхронного программированияSergey Teplyakov
 
Object-2-Object mapping, как приправа к вашему проекту
Object-2-Object mapping, как приправа к вашему проектуObject-2-Object mapping, как приправа к вашему проекту
Object-2-Object mapping, как приправа к вашему проектуAlex Tumanoff
 
Sql saturday azure storage by Anton Vidishchev
Sql saturday azure storage by Anton VidishchevSql saturday azure storage by Anton Vidishchev
Sql saturday azure storage by Anton VidishchevAlex Tumanoff
 
Bdd by Dmitri Aizenberg
Bdd by Dmitri AizenbergBdd by Dmitri Aizenberg
Bdd by Dmitri AizenbergAlex Tumanoff
 
Microsoft Office 2013 новая модель разработки приложений
Microsoft Office 2013 новая модель разработки приложенийMicrosoft Office 2013 новая модель разработки приложений
Microsoft Office 2013 новая модель разработки приложенийAlex Tumanoff
 
Patterns of parallel programming
Patterns of parallel programmingPatterns of parallel programming
Patterns of parallel programmingAlex Tumanoff
 

Viewers also liked (10)

WinDbg в руках .NET разработчика
WinDbg в руках .NET разработчикаWinDbg в руках .NET разработчика
WinDbg в руках .NET разработчика
 
Void safety on Kiev ALT.NET
Void safety on Kiev ALT.NETVoid safety on Kiev ALT.NET
Void safety on Kiev ALT.NET
 
Тонкости асинхронного программирования
Тонкости асинхронного программированияТонкости асинхронного программирования
Тонкости асинхронного программирования
 
Object-2-Object mapping, как приправа к вашему проекту
Object-2-Object mapping, как приправа к вашему проектуObject-2-Object mapping, как приправа к вашему проекту
Object-2-Object mapping, как приправа к вашему проекту
 
Design principles
Design principles Design principles
Design principles
 
Sql saturday azure storage by Anton Vidishchev
Sql saturday azure storage by Anton VidishchevSql saturday azure storage by Anton Vidishchev
Sql saturday azure storage by Anton Vidishchev
 
Bdd by Dmitri Aizenberg
Bdd by Dmitri AizenbergBdd by Dmitri Aizenberg
Bdd by Dmitri Aizenberg
 
Microsoft Office 2013 новая модель разработки приложений
Microsoft Office 2013 новая модель разработки приложенийMicrosoft Office 2013 новая модель разработки приложений
Microsoft Office 2013 новая модель разработки приложений
 
Patterns of parallel programming
Patterns of parallel programmingPatterns of parallel programming
Patterns of parallel programming
 
Mono
MonoMono
Mono
 

Similar to Deep Dive C# by Sergey Teplyakov

C#. От основ к эффективному коду
C#. От основ к эффективному кодуC#. От основ к эффективному коду
C#. От основ к эффективному кодуVasiliy Deynega
 
О сложностях программирования, или C# нас не спасет?
О сложностях программирования, или C# нас не спасет?О сложностях программирования, или C# нас не спасет?
О сложностях программирования, или C# нас не спасет?Tatyanazaxarova
 
Поговорим о JavaScript, основы и современные тенденции развития языка
Поговорим о JavaScript, основы и современные тенденции развития языкаПоговорим о JavaScript, основы и современные тенденции развития языка
Поговорим о JavaScript, основы и современные тенденции развития языкаAlexander Kucherenko
 
Михаил Давыдов — JavaScript: Базовые знания
Михаил Давыдов — JavaScript: Базовые знанияМихаил Давыдов — JavaScript: Базовые знания
Михаил Давыдов — JavaScript: Базовые знанияYandex
 
Legacy: как победить в гонке (Joker)
Legacy: как победить в гонке (Joker)Legacy: как победить в гонке (Joker)
Legacy: как победить в гонке (Joker)Victor_Cr
 
Statis code analysis
Statis code analysisStatis code analysis
Statis code analysischashnikov
 
Convert this: peculiarities of cross-platform mobile game development at Vizor
Convert this: peculiarities of cross-platform mobile game development at VizorConvert this: peculiarities of cross-platform mobile game development at Vizor
Convert this: peculiarities of cross-platform mobile game development at VizorDevGAMM Conference
 
9. java lecture library
9. java lecture library9. java lecture library
9. java lecture libraryMERA_school
 
Clojure: Lisp for the modern world (русская версия)
Clojure: Lisp for the modern world (русская версия)Clojure: Lisp for the modern world (русская версия)
Clojure: Lisp for the modern world (русская версия)Alex Ott
 
Продолжаем говорить о микрооптимизациях .NET-приложений
Продолжаем говорить о микрооптимизациях .NET-приложенийПродолжаем говорить о микрооптимизациях .NET-приложений
Продолжаем говорить о микрооптимизациях .NET-приложенийAndrey Akinshin
 
Ecma script 6 in action
Ecma script 6 in actionEcma script 6 in action
Ecma script 6 in actionYuri Trukhin
 
Solit 2014, EcmaScript 6 in Action, Трухин Юрий
Solit 2014, EcmaScript 6 in Action, Трухин Юрий Solit 2014, EcmaScript 6 in Action, Трухин Юрий
Solit 2014, EcmaScript 6 in Action, Трухин Юрий solit
 
Михаил Давыдов - JavaScript. Базовые знания
Михаил Давыдов - JavaScript. Базовые знанияМихаил Давыдов - JavaScript. Базовые знания
Михаил Давыдов - JavaScript. Базовые знанияYandex
 
Михаил Давыдов - Транспорт, ajax
Михаил Давыдов - Транспорт, ajaxМихаил Давыдов - Транспорт, ajax
Михаил Давыдов - Транспорт, ajaxYandex
 

Similar to Deep Dive C# by Sergey Teplyakov (20)

C# Deep Dive
C# Deep DiveC# Deep Dive
C# Deep Dive
 
C#. От основ к эффективному коду
C#. От основ к эффективному кодуC#. От основ к эффективному коду
C#. От основ к эффективному коду
 
О сложностях программирования, или C# нас не спасет?
О сложностях программирования, или C# нас не спасет?О сложностях программирования, или C# нас не спасет?
О сложностях программирования, или C# нас не спасет?
 
Поговорим о JavaScript, основы и современные тенденции развития языка
Поговорим о JavaScript, основы и современные тенденции развития языкаПоговорим о JavaScript, основы и современные тенденции развития языка
Поговорим о JavaScript, основы и современные тенденции развития языка
 
Михаил Давыдов — JavaScript: Базовые знания
Михаил Давыдов — JavaScript: Базовые знанияМихаил Давыдов — JavaScript: Базовые знания
Михаил Давыдов — JavaScript: Базовые знания
 
Legacy: как победить в гонке (Joker)
Legacy: как победить в гонке (Joker)Legacy: как победить в гонке (Joker)
Legacy: как победить в гонке (Joker)
 
Statis code analysis
Statis code analysisStatis code analysis
Statis code analysis
 
Convert this: peculiarities of cross-platform mobile game development at Vizor
Convert this: peculiarities of cross-platform mobile game development at VizorConvert this: peculiarities of cross-platform mobile game development at Vizor
Convert this: peculiarities of cross-platform mobile game development at Vizor
 
Bytecode
BytecodeBytecode
Bytecode
 
Reactive extensions
Reactive extensionsReactive extensions
Reactive extensions
 
9. java lecture library
9. java lecture library9. java lecture library
9. java lecture library
 
Clojure: Lisp for the modern world (русская версия)
Clojure: Lisp for the modern world (русская версия)Clojure: Lisp for the modern world (русская версия)
Clojure: Lisp for the modern world (русская версия)
 
Продолжаем говорить о микрооптимизациях .NET-приложений
Продолжаем говорить о микрооптимизациях .NET-приложенийПродолжаем говорить о микрооптимизациях .NET-приложений
Продолжаем говорить о микрооптимизациях .NET-приложений
 
Discovering Lambdas (Speech)
Discovering Lambdas (Speech)Discovering Lambdas (Speech)
Discovering Lambdas (Speech)
 
Ecma script 6 in action
Ecma script 6 in actionEcma script 6 in action
Ecma script 6 in action
 
Solit 2014, EcmaScript 6 in Action, Трухин Юрий
Solit 2014, EcmaScript 6 in Action, Трухин Юрий Solit 2014, EcmaScript 6 in Action, Трухин Юрий
Solit 2014, EcmaScript 6 in Action, Трухин Юрий
 
Funny JS #2
Funny JS #2Funny JS #2
Funny JS #2
 
Михаил Давыдов - JavaScript. Базовые знания
Михаил Давыдов - JavaScript. Базовые знанияМихаил Давыдов - JavaScript. Базовые знания
Михаил Давыдов - JavaScript. Базовые знания
 
Михаил Давыдов - Транспорт, ajax
Михаил Давыдов - Транспорт, ajaxМихаил Давыдов - Транспорт, ajax
Михаил Давыдов - Транспорт, ajax
 
Асинхронный JavaScript
Асинхронный JavaScriptАсинхронный JavaScript
Асинхронный JavaScript
 

More from Alex Tumanoff

Sql server 2019 New Features by Yevhen Nedaskivskyi
Sql server 2019 New Features by Yevhen NedaskivskyiSql server 2019 New Features by Yevhen Nedaskivskyi
Sql server 2019 New Features by Yevhen NedaskivskyiAlex Tumanoff
 
Odessa .net-user-group-sql-server-2019-hidden-gems by Denis Reznik
Odessa .net-user-group-sql-server-2019-hidden-gems by Denis ReznikOdessa .net-user-group-sql-server-2019-hidden-gems by Denis Reznik
Odessa .net-user-group-sql-server-2019-hidden-gems by Denis ReznikAlex Tumanoff
 
Azure data bricks by Eugene Polonichko
Azure data bricks by Eugene PolonichkoAzure data bricks by Eugene Polonichko
Azure data bricks by Eugene PolonichkoAlex Tumanoff
 
Sdlc by Anatoliy Anthony Cox
Sdlc by  Anatoliy Anthony CoxSdlc by  Anatoliy Anthony Cox
Sdlc by Anatoliy Anthony CoxAlex Tumanoff
 
Kostenko ux november-2014_1
Kostenko ux november-2014_1Kostenko ux november-2014_1
Kostenko ux november-2014_1Alex Tumanoff
 
Java 8 in action.jinq.v.1.3
Java 8 in action.jinq.v.1.3Java 8 in action.jinq.v.1.3
Java 8 in action.jinq.v.1.3Alex Tumanoff
 
"Drools: декларативная бизнес-логика в Java-приложениях" by Дмитрий Контрерас...
"Drools: декларативная бизнес-логика в Java-приложениях" by Дмитрий Контрерас..."Drools: декларативная бизнес-логика в Java-приложениях" by Дмитрий Контрерас...
"Drools: декларативная бизнес-логика в Java-приложениях" by Дмитрий Контрерас...Alex Tumanoff
 
Navigation map factory by Alexey Klimenko
Navigation map factory by Alexey KlimenkoNavigation map factory by Alexey Klimenko
Navigation map factory by Alexey KlimenkoAlex Tumanoff
 
Serialization and performance by Sergey Morenets
Serialization and performance by Sergey MorenetsSerialization and performance by Sergey Morenets
Serialization and performance by Sergey MorenetsAlex Tumanoff
 
Игры для мобильных платформ by Алексей Рыбаков
Игры для мобильных платформ by Алексей РыбаковИгры для мобильных платформ by Алексей Рыбаков
Игры для мобильных платформ by Алексей РыбаковAlex Tumanoff
 
Android sync adapter
Android sync adapterAndroid sync adapter
Android sync adapterAlex Tumanoff
 
Неформальные размышления о сертификации в IT
Неформальные размышления о сертификации в ITНеформальные размышления о сертификации в IT
Неформальные размышления о сертификации в ITAlex Tumanoff
 
Разработка расширений Firefox
Разработка расширений FirefoxРазработка расширений Firefox
Разработка расширений FirefoxAlex Tumanoff
 
"AnnotatedSQL - провайдер с плюшками за 5 минут" - Геннадий Дубина, Senior So...
"AnnotatedSQL - провайдер с плюшками за 5 минут" - Геннадий Дубина, Senior So..."AnnotatedSQL - провайдер с плюшками за 5 минут" - Геннадий Дубина, Senior So...
"AnnotatedSQL - провайдер с плюшками за 5 минут" - Геннадий Дубина, Senior So...Alex Tumanoff
 
Lambda выражения и Java 8
Lambda выражения и Java 8Lambda выражения и Java 8
Lambda выражения и Java 8Alex Tumanoff
 
XP практики в проектах с тяжелой наследственностью
XP практики в проектах с тяжелой наследственностьюXP практики в проектах с тяжелой наследственностью
XP практики в проектах с тяжелой наследственностьюAlex Tumanoff
 
Первые шаги во фрилансе
Первые шаги во фрилансеПервые шаги во фрилансе
Первые шаги во фрилансеAlex Tumanoff
 
Spring Web Flow. A little flow of happiness.
Spring Web Flow. A little flow of happiness.Spring Web Flow. A little flow of happiness.
Spring Web Flow. A little flow of happiness.Alex Tumanoff
 

More from Alex Tumanoff (20)

Sql server 2019 New Features by Yevhen Nedaskivskyi
Sql server 2019 New Features by Yevhen NedaskivskyiSql server 2019 New Features by Yevhen Nedaskivskyi
Sql server 2019 New Features by Yevhen Nedaskivskyi
 
Odessa .net-user-group-sql-server-2019-hidden-gems by Denis Reznik
Odessa .net-user-group-sql-server-2019-hidden-gems by Denis ReznikOdessa .net-user-group-sql-server-2019-hidden-gems by Denis Reznik
Odessa .net-user-group-sql-server-2019-hidden-gems by Denis Reznik
 
Azure data bricks by Eugene Polonichko
Azure data bricks by Eugene PolonichkoAzure data bricks by Eugene Polonichko
Azure data bricks by Eugene Polonichko
 
Sdlc by Anatoliy Anthony Cox
Sdlc by  Anatoliy Anthony CoxSdlc by  Anatoliy Anthony Cox
Sdlc by Anatoliy Anthony Cox
 
Kostenko ux november-2014_1
Kostenko ux november-2014_1Kostenko ux november-2014_1
Kostenko ux november-2014_1
 
Java 8 in action.jinq.v.1.3
Java 8 in action.jinq.v.1.3Java 8 in action.jinq.v.1.3
Java 8 in action.jinq.v.1.3
 
"Drools: декларативная бизнес-логика в Java-приложениях" by Дмитрий Контрерас...
"Drools: декларативная бизнес-логика в Java-приложениях" by Дмитрий Контрерас..."Drools: декларативная бизнес-логика в Java-приложениях" by Дмитрий Контрерас...
"Drools: декларативная бизнес-логика в Java-приложениях" by Дмитрий Контрерас...
 
Spring.new hope.1.3
Spring.new hope.1.3Spring.new hope.1.3
Spring.new hope.1.3
 
Navigation map factory by Alexey Klimenko
Navigation map factory by Alexey KlimenkoNavigation map factory by Alexey Klimenko
Navigation map factory by Alexey Klimenko
 
Serialization and performance by Sergey Morenets
Serialization and performance by Sergey MorenetsSerialization and performance by Sergey Morenets
Serialization and performance by Sergey Morenets
 
Игры для мобильных платформ by Алексей Рыбаков
Игры для мобильных платформ by Алексей РыбаковИгры для мобильных платформ by Алексей Рыбаков
Игры для мобильных платформ by Алексей Рыбаков
 
Android sync adapter
Android sync adapterAndroid sync adapter
Android sync adapter
 
Неформальные размышления о сертификации в IT
Неформальные размышления о сертификации в ITНеформальные размышления о сертификации в IT
Неформальные размышления о сертификации в IT
 
Разработка расширений Firefox
Разработка расширений FirefoxРазработка расширений Firefox
Разработка расширений Firefox
 
"AnnotatedSQL - провайдер с плюшками за 5 минут" - Геннадий Дубина, Senior So...
"AnnotatedSQL - провайдер с плюшками за 5 минут" - Геннадий Дубина, Senior So..."AnnotatedSQL - провайдер с плюшками за 5 минут" - Геннадий Дубина, Senior So...
"AnnotatedSQL - провайдер с плюшками за 5 минут" - Геннадий Дубина, Senior So...
 
Lambda выражения и Java 8
Lambda выражения и Java 8Lambda выражения и Java 8
Lambda выражения и Java 8
 
XP практики в проектах с тяжелой наследственностью
XP практики в проектах с тяжелой наследственностьюXP практики в проектах с тяжелой наследственностью
XP практики в проектах с тяжелой наследственностью
 
Anti patterns
Anti patternsAnti patterns
Anti patterns
 
Первые шаги во фрилансе
Первые шаги во фрилансеПервые шаги во фрилансе
Первые шаги во фрилансе
 
Spring Web Flow. A little flow of happiness.
Spring Web Flow. A little flow of happiness.Spring Web Flow. A little flow of happiness.
Spring Web Flow. A little flow of happiness.
 

Deep Dive C# by Sergey Teplyakov

  • 1. Deep Dive Сергей Тепляков, Visual C# MVP .NET Architect at Luxoft SergeyTeplyakov.blogspot.com
  • 2. А насколько глубоко будем нырять?
  • 3. Настолько глубоко? class X { public const int Value = 1000; } static int Foo(Func<int?, byte> x, object y) { return 1; } static int Foo(Func<X, byte> x, string y) { return 2; } var a = Foo(X => (byte)X.Value, null); unchecked { Console.WriteLine(a); } unchecked { var a = Foo(X => (byte)X.Value, null); Console.WriteLine(a); } unchecked { var a = Foo(X => (byte)X.Value, (object)null); Console.WriteLine(a); } Увидим 1Увидим 2Снова 1!!!!
  • 4. Нет! Нет! Нет! • Подробнее об этом треше - http://rsdn.ru/forum/dotnet/3272728.flat • См. этюды nikov-а на rsdn.ru – http://rsdn.ru/Forum/?fuid=55905 • Кури “The C# Programming Language” by Hejlsberg et al!
  • 5. Что нужно для работы цикла foreach? • IEnumerable? • IEnumerable of T? • Что-то еще? • Нужен метод GetEnumerator, возвращающий объект с методом MoveNext и свойством Current!
  • 6. В F# пошли еще дальше… • Поддержку цикла for можно добавить с помощью методов расширения! type Int32 with // Получаем список квадратов чисел от 1 до текущего значения member x.GetEnumerator() = ({1..x} |> Seq.map(fun x -> x*x)).GetEnumerator() // Выводит 1 4 9 16 25 for n in 5 do printf "%d " n
  • 7. Утиная типизация Если кто-то ходит, как утка, и крякает, как утка, то это и есть может быть утка индюшка с утиным адаптером...
  • 8. «Утиная типизация» в C# • foreach • Требуется GetEnumerator, MoveNext и свойство Current • http://sergeyteplyakov.blogspot.com/2012/08/duck-typing- foreach.html • LINQ (Query Comprehension syntax) • Требуются методы Select, Where, GroupBy etc. • Collection initializer • Требуется метод Add • C# 5.0 Async Features • Требуются GetAwaiter() и методы BeginAwait(Action) и EndAwait(), GetResult() и свойства IsCompleted. • System.Runtime.CompilerServices.ExtensionAttribute • Методы расширения завязаны не на конкретный тип атрибутов!
  • 9. Блоки итераторов… public static IEnumerable<string> ReadByLine(string path) { if (string.IsNullOrEmpty(path)) throw new ArgumentNullException("path"); using (var sr = new StreamReader(path)) { string s; while ((s = sr.ReadLine()) != null) yield return s; } } var seq = ReadByLine(null); // 1 var s = seq.Select(line => line.Length); // 2 Console.WriteLine(s.Max()); // 3 Все ли нормально с кодом? Этот же подход используется и для асинхронных методов! Когда получим исключение? Код до первого yield return вызовется при первом вызове метода MoveNext!
  • 10. Какое исключение получим? class Foo { public Foo() { throw new Exception("Ooops!!"); } } static T Create<T>() where T : new() { var instance = new T(); // Write to log some message return instance; } var f = Create<Foo>(); Какое исключение получим?
  • 11. Почему? • Используется reflection (Activator.CreateInstance). • Все обобщения должны содержать одну реализацию! • Вызов метода через Reflection всегда «оборачивает» исходное исключение в TargetInvocationException • «Все нетривиальные абстракции текут» Джоэл Спольски
  • 12. Повторная генерация исключений • Делаем "правильную" фабрику. Наивная реализация: public static T CreateInstanceNaive<T>() where T : new() { try { return new T(); } catch (TargetInvocationException e) { // Исходный стек вызовов потерян, теперь все // будут думать, что виноваты мы! throw e.InnerException; } }
  • 13. Используем ExceptionDispatchInfo public static T CreateInstance<T>() where T : new() { try { return new T(); } catch(TargetInvocationException e) { ExceptionDispatchInfo di = ExceptionDispatchInfo.Capture(e.InnerException); di.Throw(); // компилятор C# не знает, что эта точка недостижима return default(T); } }
  • 14. Quiz #3. Исключение в блоке finally public static void FinallyThatThrows() { try { throw new Exception("1"); } catch(Exception e) { throw new Exception("2"); } finally { throw new Exception("3"); } } try { FinallyThatThrows(); } catch(Exception e) { Console.WriteLine(e.Message); } Что получим? "1", "2" или "3"?
  • 15. Quiz # 4. Маскирование исключений в блоке using class CustomDisposable : IDisposable { public void Dispose() { throw new InvalidOperationException("Ooops!!"); } } // Какое исключение перехватывать? using (var disposable = new CustomDisposable()) { throw new FileNotFoundException(); }
  • 16. Подходы к потерянным исключениям • C# - побеждает исключение из finally. Исходное теряем • С++ • Исключение в деструкторе – UB ;) • std::unexpected, если деструктор вызван при раскрутке стека • Java • Исключение в блоке try-finally • Тоже самое, что и в C# • try-with-resources • Побеждает исключение из finally, но исходное остается в скрытых исключениях
  • 17. Quiz #6. Создание объекта class Base : IDisposable { public Base() { // Выделяем ресурсы! } public void Dispose() { Console.WriteLine("Base.Dispose"); } } class Derived : Base { public Derived(object data) { if (data == null) throw new ArgumentNullException("data"); // Oops!!! } } Что будет в этом случае?
  • 18. Обработка ошибок… public static IEnumerable<string> ReadByLine(string path) { if (string.IsNullOrEmpty(path)) throw new ArgumentNullException("path"); using (var sr = new StreamReader(path)) { string s; while ((s = sr.ReadLine()) != null) yield return s; } } var seq = ReadByLine(null); // 1 var s = seq.Select(line => line.Length); // 2 Console.WriteLine(s.Max()); // 3 Все ли нормально с кодом? Этот же подход используется и для асинхронных методов! Когда получим исключение? Код до первого yield return вызовется при первом вызове метода MoveNext!
  • 19. Корректная реализация public static IEnumerable<string> ReadByLine(string path) { if (string.IsNullOrEmpty(path)) throw new ArgumentNullException("path"); return ReadByLineImpl(path); } private static IEnumerable<string> ReadByLineImpl(string path) { using (var sr = new StreamReader(path)) { string s; while ((s = sr.ReadLine()) != null) yield return s; } } Наличие блока итераторов принципиально изменяет реализацию метода! var seq = ReadByLine(null); // 1 var s = seq.Select(line => line.Length); // 2 Console.WriteLine(s.Max()); // 3
  • 20. В чем разница? • Исключение при вызове метода – ошибка в вызывающем коде • Исключение во время перебора элементов – ошибка/проблема в вызываемом коде!
  • 21. Необязательные аргументы и полиморфизм class Base { public virtual void Foo(int i = 42) { Console.WriteLine("Base.Foo: i = {0}", i); } } class Derived : Base { public override void Foo(int i = 0) { Console.WriteLine("Derived.Foo: i = {0}", i); } } void Main() { Derived d = new Derived(); Base b = d; b.Foo(); d.Foo(); } Вызываем через Base!Вызываем через Derived!
  • 22. Что будет в этом случае? // 1 void WithDateTime(DateTime dt = DateTime.Now) { } // 2 void WithStringEmpty(string s = String.Empty) { } // 3 void WithEmptyString(string s = "") { } // 4 void WithMethodCall(int id = GetInvalidId()) { } static int GetInvalidId() { return -1; }
  • 23. Примерная реализация // Декларация void WithEmptyString(string s = "") { } // Вызов WithEmptyString(); // Декларация [Optional, DefaultParameterValue(value: "")] static void WithEmptyString(string s) {} // Вызов string defaultValue = GetDefaultValueFromMetadata(); WithEmptyString(defaultValue);
  • 24. Можно ли изменить неизменяемое? (или как можно изменить readonly поля?)
  • 25. Вот пример! • Как поменять C1.X? class C1 { public readonly int X = 42; } • Рефлекшн. Но это скушно! class C2 { public int X; } [StructLayout(LayoutKind.Explicit)] class C1Modifier { [FieldOffset(0)] public C1 C1; [FieldOffset(0)] public C2 C2; } var c1 = new C1(); // c1.X == 42 // Можификация одного поля приводит к модификации другого! var c1Modifier = new C1Modifier {C1 = c1}; c1Modifier.C2.X = -1; // c1.X == -1 Console.WriteLine(c1.X); Создаем класс с таким же «расположением» Создаем «объединение» (union) из двух таких классов
  • 26. Ковариантность массивов • Что такое ковариантность массивов? • Вот пример: object[] o = new string[]{"s1", "s2", "s3"}; • Что в этом опасного? o[0] = new StringBuilder(); • Это требует проверки типа аргумента во время исполнения! • Почему? • Так было в Java!! ArrayTypeMismatchException!
  • 28. Внутреннее устройство массива Flags, ... Length (4) 42 (Element 0) 41 (Element 1) 40 (Element 2) 39 (Element 3) arr[0] var arr = new int[] {42, 41, 40, 39}; Flags, ... Length (4) Type Indentifier (System.String) 1 (Element 0) 2 (Element 1) 3 (Element 2) 4 (Element 3) arr[0] var arr = new string[] {"1", "2", "3", "4"};
  • 29. Изменяем размер массива [StructLayout(LayoutKind.Explicit)] class RefArrayLayout { [FieldOffset(0)] public int Length; } [StructLayout(LayoutKind.Explicit)] class ArrayExplorer { [FieldOffset(0)] public object[] Array; [FieldOffset(0)] public RefArrayLayout Layout; } var array = new string[] {"1", "2"}; // array.Length = 2 var ae = new ArrayExplorer {Array = array}; ae.Layout.Length = 42; // Получаем 42 Console.WriteLine(array.Length);
  • 30. Значимые типы (Value Types) • В чем главная разница между значимыми и ссылочными типами? The most relevant fact about value types is not the implementation detail of how they are allocated, but rather the by-design semantic meaning of “value type”, namely that they are always copied “by value” Eric Lippert
  • 31. Метод GetHashCode • Нужно ли переопределять у структур метод GetHashCode? • Какова реализация этого метода по умолчанию? • Корректна ли она?
  • 32. Пример встроенного метода GetHashCode public struct KeyValuePair<TKey, TValue> { public TKey Key; public TValue Value; } public struct KeyValuePair { public static KeyValuePair<TKey, TValue> Create<TKey, TValue>( TKey key, TValue value) { return new KeyValuePair<TKey, TValue>() { Key = key, Value = value }; } } Используем реализацию Equals и GetHashCode по умолчанию
  • 33. Тонкости реализации • KeyValuePair<int, string>: var kvp1 = KeyValuePair.Create(42, "Foo"); var kvp2 = KeyValuePair.Create(42, "Boo"); Console.WriteLine(kvp1.GetHashCode() == kvp2.GetHashCode()); Console.WriteLine(kvp1.Equals(kvp2)); • KeyValuePair<int, int>: var kvp1 = KeyValuePair.Create(42, 42); var kvp2 = KeyValuePair.Create(42, 43); Console.WriteLine(kvp1.GetHashCode() == kvp2.GetHashCode()); Console.WriteLine(kvp1.Equals(kvp2)); • Одинаковый ли хэш-коды? • Равны ли объекты?
  • 34. Тонкости реализации (2) • ValueType.GetHashCode() содержит две реализации: • Быструю и точную: • Структура не содержит «пробелов» в содержимом структуры и ссылочных типов. • Используется бинарное представление всего содержимого структуры. • Быструю и неточную: • Структура содержит «пробелов» в содержимом или ссылочные типы. • Используется лишь первое поле структуры. • Подробнее – Why is ValueType.GetHashCode() implemented like it is?
  • 37. Чего еще почитать? • Programming Stuff • C# Tips and Tricks • Chris Burrows’ Blog • Eric Lippert’s Blog • Joe Duffy’s Weblog • B# .NET BLOG
  • 38. More C# Deep Dive on Programming Stuff • this == null? • Замыкания в языке C# • Перегрузка и наследование • Структуры и конструкторы по умолчанию • О вреде изменяемых значимых типов. • Часть 1 • Часть 2 • MVP Summit. День 0. Кэширование делегатов • MVP Summit. День 1. Об эффективности
  • 39. Спасибо за внимание • Сергей Тепляков, Visual C# MVP • .NET Architect at Luxoft • Sergey.Teplyakov@gmail.com • http://sergeyteplyakov.blogspot.com/

Editor's Notes

  1. Тут приходит в голову очень пошлая фотка)
  2. Обязательно сказать, что traceability – очень важная составляющая любого приложения.Поэтому если вы где-либо логируете лишь ex.Message, то писать вам всегда на языке С! (это ведь страшнее, чем гореть в аду в страшных муках).
  3. Получим &quot;3&quot;.Сказать, что это важно, поскольку эта же самая проблема, но в несколько завуалированном виде возникает достаточно часто!
  4. Применимо в том же WCF-е! Когда Dispose приводит к закрытию клиента в результате чего исходное исключение теряется!
  5. У жабы в try-with-resources – самый четкий подход!!!Сказать, что у этой проблемы нет простого решения!
  6. Да, тут можно сказать, что в С++\CLI все будет зашибись! Как и в старом С++!
  7. Продолжаем тему обработки исключений.
  8. И теперь мы «упадем» в первой строке!
  9. TODO: Рисунок с контрактами!
  10. Это не сверх полезная информация, тем не менее, у нее есть и некоторые любопытные особенности.
  11. Но прежде чем переходить к
  12. Объекты не равны в обоих случаях, но в первом случае методы GetHashCode возвращают один и тот же результат!
  13. Посмотрите заметку по ссылке, чтобы понять, о чем идет речь!
  14. // TODO: Сделать пометки, почему ведет себя код именно так! Сказать, что readonly – доступ к ней – это не обращение к переменной, а получение значения! Добавить b.M.Y++, что это тоже не компилится, поскольку b.M - rvalue