Об особенностях использования значимых типов в .NET

Andrey Akinshin
Andrey AkinshinSoftware developer at JetBrains
Об особенностях использования значимых типов в .NET
Андрей Акиньшин

Барнаульское сообщество .NET разработчиков
bug.ineta.ru
www.facebook.com/groups/dotnetbarnaul/
Структуры

•
•
•
•
•

Копирование по значению
Поддержка boxed и unboxed формы
Всегда инициализированы
Методы из Equals, GetHashCode из System.ValueType
Не могут быть базовыми типами
Изменяемые значимые типы
public struct Point
{
public int X, Y;
public void Move(int dx, int dy)
{
X += dx;
Y += dy;
}
}
public class Circle
{
public Point Center; // Поле
}
var circle = new Circle();
circle.Center = new Point { X = 0, Y = 0 };
circle.Center.Move(5, 5);
Console.WriteLine(circle.Center.X);
Изменяемые значимые типы
public struct Point
{
public int X, Y;
public void Move(int dx, int dy)
{
X += dx;
Y += dy;
}
}
public class Circle
{
public Point Center { get; set; } // Свойство
}
var circle = new Circle();
circle.Center = new Point { X = 0, Y = 0 };
circle.Center.Move(5, 5);
Console.WriteLine(circle.Center.X);
Изменяемые значимые типы
Будут проблемы:
// 1. Property
public class Circle
{
public Point Center { get; set; }
}
// 2. Readonly field
public class Circle
{
public readonly Point Center = new Point();
}
// 3. IList
var points = new List<Point>();
Изменяемые значимые типы

public struct Enumerator : IEnumerator<T>, IDisposable,
IEnumerator
var x = new
{
Items = new List<int> { 1, 2, 3 }.GetEnumerator()
};
while (x.Items.MoveNext())
Console.WriteLine(x.Items.Current);
Изменяемые значимые типы

struct Disposable : IDisposable
{
public bool Disposed { get; private set; }
public void Dispose() { Disposed = true; }
}
var d = new Disposable();
using (d)
{
// Some code
}
Console.WriteLine(d.Disposed);
Упаковка и распаковка
// 1
var arrayList = new ArrayList();
var p = new Point();
arrayList.Add(p);
// Упаковка
p = (Point) arrayList[0];
// Распаковка
Упаковка и распаковка
// 1
var arrayList = new ArrayList();
var p = new Point();
arrayList.Add(p);
// Упаковка
p = (Point) arrayList[0];
// Распаковка
// 2
Int32 x = 5;
Object o = x;
// Упаковка
Int16 y = (Int16) o;
// InvalidCastException
Int16 z = (Int16)(Int32) o; // Распаковка и приведение
Упаковка и распаковка
// 1
var arrayList = new ArrayList();
var p = new Point();
arrayList.Add(p);
// Упаковка
p = (Point) arrayList[0];
// Распаковка
// 2
Int32 x = 5;
Object o = x;
// Упаковка
Int16 y = (Int16) o;
// InvalidCastException
Int16 z = (Int16)(Int32) o; // Распаковка и приведение
// 3
Int32 x = 1;
Object y = x;
x = 2;
Console.WriteLine(x + "/" + (Int32)y);// "2/1"
Упаковка и распаковка
interface IChangeable
{
void Change(int x, int y);
}
struct Point : IChangeable
{
public int X, Y;
public void Change(int x, int y)
{
X = x;
Y = y;
}
public override string ToString()
{
return X + "," + Y;
}
}
Упаковка и распаковка
var p = new Point {X = 1, Y = 1};
Console.WriteLine(p);
p.Change(2, 2);
Console.WriteLine(p);
Object o = p;
Console.WriteLine(o);
((Point) o).Change(3, 3);
Console.WriteLine(o);
((IChangeable)p).Change(4, 4);
Console.WriteLine(p);
((IChangeable)o).Change(5, 5);
Console.WriteLine(o);
Конструкторы по умолчанию

• .NET поддерживает конструкторы по умолчанию для

структур
Конструкторы по умолчанию

• .NET поддерживает конструкторы по умолчанию для

структур
• А C# — нет
Конструкторы по умолчанию

• .NET поддерживает конструкторы по умолчанию для

структур
• А C# — нет
• Но мы всё равно создадим структуру с конструктором
по умолчанию, которую назовём MyStruct
Конструкторы по умолчанию

// Вспомогательные методы
static T CreateAsDefault<T>() { return default(T); }
static T CreateWithNew<T>() where T : new() { return new T(); }
// Вызывается
var m = Activator.CreateInstance(typeof(MyStruct));
var m = new MyStruct();
// Не вызывается
var m = default(MyStruct);
var m = CreateWithNew<MyStruct>();
var m = CreateAsDefault<MyStruct>();
var array = new MyStruct[100];
GetHashCode()

• Быстрая версия

(Структура не имеет ссылочных полей, а между её
полями нет свободного места)
Используем Xor каждых 4 байта структуры
• Медленная версия
Используем GetHashCode первого нестатичного поля
GetHashCode()

var a1 = new KeyValuePair<int, int>(1, 2);
var a2 = new KeyValuePair<int, int>(1, 3);
Console.WriteLine(a1.GetHashCode()); // 1033533110
Console.WriteLine(a2.GetHashCode()); // 1033533111
var b1 = new KeyValuePair<int, string>(1, "x");
var b2 = new KeyValuePair<int, string>(1, "y");
Console.WriteLine(b1.GetHashCode()); // -1888265882
Console.WriteLine(b2.GetHashCode()); // -1888265882
Equals()
public override bool Equals (Object obj) {
// ...
FieldInfo[] thisFields = thisType.GetFields(
BindingFlags.Instance |
BindingFlags.Public |
BindingFlags.NonPublic);
for (int i=0; i<thisFields.Length; i++) {
thisResult = ((RtFieldInfo)thisFields[i]).
InternalGetValue(thisObj,false);
thatResult = ((RtFieldInfo)thisFields[i]).
InternalGetValue(obj, false);
if (thisResult == null) {
if (thatResult != null)
return false;
} else if (!thisResult.Equals(thatResult))
return false;
}
return true;
}
Equals()
var redName = Color.Red;
var redArgb = Color.FromArgb(255, 255, 0, 0);
Console.WriteLine(redName == redArgb);
Equals()
var redName = Color.Red;
var redArgb = Color.FromArgb(255, 255, 0, 0);
Console.WriteLine(redName == redArgb);
public struct Color {
private readonly long value;
private readonly string name;
private readonly short knownColor, state;
public static bool operator ==(Color left, Color right) {
if (left.value == right.value &&
left.state == right.state &&
left.knownColor == right.knownColor) {
if (left.name == right.name)
return true;
if (left.name == (object) null ||
right.name == (object) null)
return false;
return left.name.Equals(right.name);
}
return false;
}
}
Размещение в памяти
public struct S1
{
public byte Byte1;
public int Int1;
}
public struct S2
{
public byte Byte1;
public byte Byte2;
public byte Byte3;
public byte Byte4;
public int Int1;
}
Console.WriteLine(Marshal.SizeOf(typeof(S1)));
Console.WriteLine(Marshal.SizeOf(typeof(S2)));
Размещение в памяти

[StructLayout(LayoutKind.Explicit)]
struct MyStruct
{
[FieldOffset(0)]
public Int16 Value;
[FieldOffset(0)]
public Byte LowByte;
}
var s = new MyStruct();
s.Value = 256 + 100;
Console.WriteLine(s.LowByte); // 100
Размещение в памяти
namespace System.Drawing {
public struct Color {
/**
* Shift count and bit mask for A, R, G, B
* components in ARGB mode!
*/
private const int ARGBAlphaShift = 24;
private const int ARGBRedShift
= 16;
private const int ARGBGreenShift = 8;
private const int ARGBBlueShift
= 0;
///
///
///
///
///
///
///
}
}

WARNING!!! WARNING!!! WARNING!!! WARNING!!!
WARNING!!! WARNING!!! WARNING!!! WARNING!!!
We can never change the layout of this class (adding
or removing or changing the order of member variables)
if you want to be compatible v1.0 version of the runtime
This is so that we can push into the runtime a custom
marshaller for OLE_COLOR to Color.
Хорошие книжки
Блоги

• http://msdn.microsoft.com/magazine/
• http://www.rsdn.ru/
• http://blogs.msdn.com/b/ericlippert/
• http://sergeyteplyakov.blogspot.ru/
• http://timyrguev.blogspot.ru/
• http://aakinshin.blogspot.ru/
Спасибо за внимание!
1 of 27

Recommended

Поговорим о микрооптимизациях .NET-приложений by
Поговорим о микрооптимизациях .NET-приложенийПоговорим о микрооптимизациях .NET-приложений
Поговорим о микрооптимизациях .NET-приложенийAndrey Akinshin
855 views69 slides
Продолжаем говорить о микрооптимизациях .NET-приложений by
Продолжаем говорить о микрооптимизациях .NET-приложенийПродолжаем говорить о микрооптимизациях .NET-приложений
Продолжаем говорить о микрооптимизациях .NET-приложенийAndrey Akinshin
665 views58 slides
Павел Сушин «Асинхронное программирование на С++: callbacks, futures, fibers» by
Павел Сушин «Асинхронное программирование на С++: callbacks, futures, fibers»Павел Сушин «Асинхронное программирование на С++: callbacks, futures, fibers»
Павел Сушин «Асинхронное программирование на С++: callbacks, futures, fibers»Platonov Sergey
1.7K views33 slides
Игорь Кудрин, «Используем неизменяемые данные и создаем качественный код» by
Игорь Кудрин, «Используем неизменяемые данные и создаем качественный код»Игорь Кудрин, «Используем неизменяемые данные и создаем качественный код»
Игорь Кудрин, «Используем неизменяемые данные и создаем качественный код»Platonov Sergey
1.5K views96 slides
Распространённые ошибки оценки производительности .NET-приложений by
Распространённые ошибки оценки производительности .NET-приложенийРаспространённые ошибки оценки производительности .NET-приложений
Распространённые ошибки оценки производительности .NET-приложенийMikhail Shcherbakov
518 views64 slides
Фитнес для вашего кода: как держать его в форме by
Фитнес для вашего кода: как держать его в формеФитнес для вашего кода: как держать его в форме
Фитнес для вашего кода: как держать его в формеIlia Shishkov
5.9K views60 slides

More Related Content

What's hot

Оптимизация производительности Python by
Оптимизация производительности PythonОптимизация производительности Python
Оптимизация производительности PythonPyNSK
717 views216 slides
20130429 dynamic c_c++_program_analysis-alexey_samsonov by
20130429 dynamic c_c++_program_analysis-alexey_samsonov20130429 dynamic c_c++_program_analysis-alexey_samsonov
20130429 dynamic c_c++_program_analysis-alexey_samsonovComputer Science Club
1.3K views67 slides
PVS-Studio в 2021 - Примеры ошибок by
PVS-Studio в 2021 - Примеры ошибокPVS-Studio в 2021 - Примеры ошибок
PVS-Studio в 2021 - Примеры ошибокAndrey Karpov
56 views30 slides
Лекция 8: Многопоточное программирование: Intel Threading Building Blocks by
Лекция 8: Многопоточное программирование: Intel Threading Building BlocksЛекция 8: Многопоточное программирование: Intel Threading Building Blocks
Лекция 8: Многопоточное программирование: Intel Threading Building BlocksMikhail Kurnosov
1.6K views54 slides
Григорий Демченко, Универсальный адаптер by
Григорий Демченко, Универсальный адаптерГригорий Демченко, Универсальный адаптер
Григорий Демченко, Универсальный адаптерSergey Platonov
6.1K views31 slides
Догнать и перегнать boost::lexical_cast by
Догнать и перегнать boost::lexical_castДогнать и перегнать boost::lexical_cast
Догнать и перегнать boost::lexical_castRoman Orlov
7.1K views42 slides

What's hot(19)

Оптимизация производительности Python by PyNSK
Оптимизация производительности PythonОптимизация производительности Python
Оптимизация производительности Python
PyNSK717 views
20130429 dynamic c_c++_program_analysis-alexey_samsonov by Computer Science Club
20130429 dynamic c_c++_program_analysis-alexey_samsonov20130429 dynamic c_c++_program_analysis-alexey_samsonov
20130429 dynamic c_c++_program_analysis-alexey_samsonov
PVS-Studio в 2021 - Примеры ошибок by Andrey Karpov
PVS-Studio в 2021 - Примеры ошибокPVS-Studio в 2021 - Примеры ошибок
PVS-Studio в 2021 - Примеры ошибок
Andrey Karpov56 views
Лекция 8: Многопоточное программирование: Intel Threading Building Blocks by Mikhail Kurnosov
Лекция 8: Многопоточное программирование: Intel Threading Building BlocksЛекция 8: Многопоточное программирование: Intel Threading Building Blocks
Лекция 8: Многопоточное программирование: Intel Threading Building Blocks
Mikhail Kurnosov1.6K views
Григорий Демченко, Универсальный адаптер by Sergey Platonov
Григорий Демченко, Универсальный адаптерГригорий Демченко, Универсальный адаптер
Григорий Демченко, Универсальный адаптер
Sergey Platonov6.1K views
Догнать и перегнать boost::lexical_cast by Roman Orlov
Догнать и перегнать boost::lexical_castДогнать и перегнать boost::lexical_cast
Догнать и перегнать boost::lexical_cast
Roman Orlov7.1K views
Антон Полухин, Немного о Boost by Sergey Platonov
Антон Полухин, Немного о BoostАнтон Полухин, Немного о Boost
Антон Полухин, Немного о Boost
Sergey Platonov1K views
Алексей Куканов — Параллелизм в C++: управляйте приложением, а не потоками! by Yandex
Алексей Куканов — Параллелизм в C++: управляйте приложением, а не потоками!Алексей Куканов — Параллелизм в C++: управляйте приложением, а не потоками!
Алексей Куканов — Параллелизм в C++: управляйте приложением, а не потоками!
Yandex2.6K views
Юрий Ефимочев, Компилируемые в реальном времени DSL для С++ by Sergey Platonov
Юрий Ефимочев, Компилируемые в реальном времени DSL для С++ Юрий Ефимочев, Компилируемые в реальном времени DSL для С++
Юрий Ефимочев, Компилируемые в реальном времени DSL для С++
Sergey Platonov813 views
Григорий Демченко, “Асинхронность и сопрограммы: обработка данных“ by Platonov Sergey
Григорий Демченко, “Асинхронность и сопрограммы: обработка данных“Григорий Демченко, “Асинхронность и сопрограммы: обработка данных“
Григорий Демченко, “Асинхронность и сопрограммы: обработка данных“
Platonov Sergey1.3K views
Магия в Python: Дескрипторы. Что это? by PyNSK
Магия в Python: Дескрипторы. Что это?Магия в Python: Дескрипторы. Что это?
Магия в Python: Дескрипторы. Что это?
PyNSK3.1K views
Продолжаем говорить про арифметику by Andrey Akinshin
Продолжаем говорить про арифметикуПродолжаем говорить про арифметику
Продолжаем говорить про арифметику
Andrey Akinshin676 views
Лекция 8. Intel Threading Building Blocks by Mikhail Kurnosov
Лекция 8. Intel Threading Building BlocksЛекция 8. Intel Threading Building Blocks
Лекция 8. Intel Threading Building Blocks
Mikhail Kurnosov1.3K views
Статический анализ кода by Pavel Tsukanov
Статический анализ кода Статический анализ кода
Статический анализ кода
Pavel Tsukanov689 views
Дмитрий Кашицын, Троллейбус из буханки: алиасинг и векторизация в LLVM by Sergey Platonov
Дмитрий Кашицын, Троллейбус из буханки: алиасинг и векторизация в LLVMДмитрий Кашицын, Троллейбус из буханки: алиасинг и векторизация в LLVM
Дмитрий Кашицын, Троллейбус из буханки: алиасинг и векторизация в LLVM
Sergey Platonov2.8K views
хитрости выведения типов by corehard_by
хитрости выведения типовхитрости выведения типов
хитрости выведения типов
corehard_by333 views
Быстрые конструкции в Python - Олег Шидловский, Python Meetup 26.09.2014 by Python Meetup
Быстрые конструкции в Python - Олег Шидловский, Python Meetup 26.09.2014Быстрые конструкции в Python - Олег Шидловский, Python Meetup 26.09.2014
Быстрые конструкции в Python - Олег Шидловский, Python Meetup 26.09.2014
Python Meetup4.5K views
Производительность в Django by MoscowDjango
Производительность в DjangoПроизводительность в Django
Производительность в Django
MoscowDjango2.5K views

Similar to Об особенностях использования значимых типов в .NET

C sharp deep dive by
C sharp deep diveC sharp deep dive
C sharp deep diveSergey Teplyakov
1.3K views29 slides
C# Deep Dive by
C# Deep DiveC# Deep Dive
C# Deep DiveLuxoftTraining
752 views29 slides
Язык программирования C# by
Язык программирования C#Язык программирования C#
Язык программирования C#Dmitri Soshnikov
3.2K views14 slides
C#. От основ к эффективному коду by
C#. От основ к эффективному кодуC#. От основ к эффективному коду
C#. От основ к эффективному кодуVasiliy Deynega
917 views17 slides
[JAM 1.1] Clean Code (Paul Malikov) by
[JAM 1.1] Clean Code (Paul Malikov)[JAM 1.1] Clean Code (Paul Malikov)
[JAM 1.1] Clean Code (Paul Malikov)Evgeny Kaziak
551 views55 slides
Школа-студия разработки приложений для iOS. Лекция 1. Objective-C by
Школа-студия разработки приложений для iOS. Лекция 1. Objective-CШкола-студия разработки приложений для iOS. Лекция 1. Objective-C
Школа-студия разработки приложений для iOS. Лекция 1. Objective-CГлеб Тарасов
1.6K views116 slides

Similar to Об особенностях использования значимых типов в .NET(20)

Язык программирования C# by Dmitri Soshnikov
Язык программирования C#Язык программирования C#
Язык программирования C#
Dmitri Soshnikov3.2K views
C#. От основ к эффективному коду by Vasiliy Deynega
C#. От основ к эффективному кодуC#. От основ к эффективному коду
C#. От основ к эффективному коду
Vasiliy Deynega917 views
[JAM 1.1] Clean Code (Paul Malikov) by Evgeny Kaziak
[JAM 1.1] Clean Code (Paul Malikov)[JAM 1.1] Clean Code (Paul Malikov)
[JAM 1.1] Clean Code (Paul Malikov)
Evgeny Kaziak551 views
Школа-студия разработки приложений для iOS. Лекция 1. Objective-C by Глеб Тарасов
Школа-студия разработки приложений для iOS. Лекция 1. Objective-CШкола-студия разработки приложений для iOS. Лекция 1. Objective-C
Школа-студия разработки приложений для iOS. Лекция 1. Objective-C
Некоторые паттерны реализации полиморфного поведения в C++ – Дмитрий Леванов,... by Yandex
Некоторые паттерны реализации полиморфного поведения в C++ – Дмитрий Леванов,...Некоторые паттерны реализации полиморфного поведения в C++ – Дмитрий Леванов,...
Некоторые паттерны реализации полиморфного поведения в C++ – Дмитрий Леванов,...
Yandex20.1K views
Programming Java - Lecture 02 - Objects - Lavrentyev Fedor by Fedor Lavrentyev
Programming Java - Lecture 02 - Objects - Lavrentyev FedorProgramming Java - Lecture 02 - Objects - Lavrentyev Fedor
Programming Java - Lecture 02 - Objects - Lavrentyev Fedor
Fedor Lavrentyev402 views
Groovy и Grails. Быстро и обо всём by Ruslan Balkin
Groovy и Grails. Быстро и обо всёмGroovy и Grails. Быстро и обо всём
Groovy и Grails. Быстро и обо всём
Ruslan Balkin558 views
2.2 Стек вызовов by DEVTYPE
2.2 Стек вызовов2.2 Стек вызовов
2.2 Стек вызовов
DEVTYPE578 views
Статический и динамический полиморфизм в C++, Дмитрий Леванов by Yandex
Статический и динамический полиморфизм в C++, Дмитрий ЛевановСтатический и динамический полиморфизм в C++, Дмитрий Леванов
Статический и динамический полиморфизм в C++, Дмитрий Леванов
Yandex2.1K views
Statis code analysis by chashnikov
Statis code analysisStatis code analysis
Statis code analysis
chashnikov1.4K views
C# Desktop. Занятие 03. by Igor Shkulipa
C# Desktop. Занятие 03.C# Desktop. Занятие 03.
C# Desktop. Занятие 03.
Igor Shkulipa315 views
Распространённые ошибки оценки производительности .NET-приложений by Andrey Akinshin
Распространённые ошибки оценки производительности .NET-приложенийРаспространённые ошибки оценки производительности .NET-приложений
Распространённые ошибки оценки производительности .NET-приложений
Andrey Akinshin1K views
Дмитрий Прокопцев — R-ссылки в С++11 by Yandex
Дмитрий Прокопцев — R-ссылки в С++11Дмитрий Прокопцев — R-ссылки в С++11
Дмитрий Прокопцев — R-ссылки в С++11
Yandex1.2K views
Deep Dive C# by Sergey Teplyakov by Alex Tumanoff
Deep Dive  C# by Sergey TeplyakovDeep Dive  C# by Sergey Teplyakov
Deep Dive C# by Sergey Teplyakov
Alex Tumanoff5K views

More from Andrey Akinshin

Поговорим про performance-тестирование by
Поговорим про performance-тестированиеПоговорим про performance-тестирование
Поговорим про performance-тестированиеAndrey Akinshin
368 views105 slides
Сложности performance-тестирования by
Сложности performance-тестированияСложности performance-тестирования
Сложности performance-тестированияAndrey Akinshin
277 views91 slides
Сложности микробенчмаркинга by
Сложности микробенчмаркингаСложности микробенчмаркинга
Сложности микробенчмаркингаAndrey Akinshin
521 views66 slides
Поговорим про память by
Поговорим про памятьПоговорим про память
Поговорим про памятьAndrey Akinshin
332 views116 slides
Кроссплатформенный .NET и как там дела с Mono и CoreCLR by
Кроссплатформенный .NET и как там дела с Mono и CoreCLRКроссплатформенный .NET и как там дела с Mono и CoreCLR
Кроссплатформенный .NET и как там дела с Mono и CoreCLRAndrey Akinshin
322 views32 slides
Теория и практика .NET-бенчмаркинга (25.01.2017, Москва) by
 Теория и практика .NET-бенчмаркинга (25.01.2017, Москва) Теория и практика .NET-бенчмаркинга (25.01.2017, Москва)
Теория и практика .NET-бенчмаркинга (25.01.2017, Москва)Andrey Akinshin
3.6K views153 slides

More from Andrey Akinshin(17)

Поговорим про performance-тестирование by Andrey Akinshin
Поговорим про performance-тестированиеПоговорим про performance-тестирование
Поговорим про performance-тестирование
Andrey Akinshin368 views
Сложности performance-тестирования by Andrey Akinshin
Сложности performance-тестированияСложности performance-тестирования
Сложности performance-тестирования
Andrey Akinshin277 views
Сложности микробенчмаркинга by Andrey Akinshin
Сложности микробенчмаркингаСложности микробенчмаркинга
Сложности микробенчмаркинга
Andrey Akinshin521 views
Поговорим про память by Andrey Akinshin
Поговорим про памятьПоговорим про память
Поговорим про память
Andrey Akinshin332 views
Кроссплатформенный .NET и как там дела с Mono и CoreCLR by Andrey Akinshin
Кроссплатформенный .NET и как там дела с Mono и CoreCLRКроссплатформенный .NET и как там дела с Mono и CoreCLR
Кроссплатформенный .NET и как там дела с Mono и CoreCLR
Andrey Akinshin322 views
Теория и практика .NET-бенчмаркинга (25.01.2017, Москва) by Andrey Akinshin
 Теория и практика .NET-бенчмаркинга (25.01.2017, Москва) Теория и практика .NET-бенчмаркинга (25.01.2017, Москва)
Теория и практика .NET-бенчмаркинга (25.01.2017, Москва)
Andrey Akinshin3.6K views
Let’s talk about microbenchmarking by Andrey Akinshin
Let’s talk about microbenchmarkingLet’s talk about microbenchmarking
Let’s talk about microbenchmarking
Andrey Akinshin598 views
Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург) by Andrey Akinshin
Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)
Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)
Andrey Akinshin1.4K views
Подружили CLR и JVM в Project Rider by Andrey Akinshin
Подружили CLR и JVM в Project RiderПодружили CLR и JVM в Project Rider
Подружили CLR и JVM в Project Rider
Andrey Akinshin794 views
Что нам готовит грядущий C#7? by Andrey Akinshin
Что нам готовит грядущий C#7?Что нам готовит грядущий C#7?
Что нам готовит грядущий C#7?
Andrey Akinshin376 views
.NET 2015: Будущее рядом by Andrey Akinshin
.NET 2015: Будущее рядом.NET 2015: Будущее рядом
.NET 2015: Будущее рядом
Andrey Akinshin538 views
Практические приёмы оптимизации .NET-приложений by Andrey Akinshin
Практические приёмы оптимизации .NET-приложенийПрактические приёмы оптимизации .NET-приложений
Практические приёмы оптимизации .NET-приложений
Andrey Akinshin2.4K views
Поговорим о различных версиях .NET by Andrey Akinshin
Поговорим о различных версиях .NETПоговорим о различных версиях .NET
Поговорим о различных версиях .NET
Andrey Akinshin726 views
Низкоуровневые оптимизации .NET-приложений by Andrey Akinshin
Низкоуровневые оптимизации .NET-приложенийНизкоуровневые оптимизации .NET-приложений
Низкоуровневые оптимизации .NET-приложений
Andrey Akinshin3.8K views
Основы работы с Git by Andrey Akinshin
Основы работы с GitОсновы работы с Git
Основы работы с Git
Andrey Akinshin3.8K views
Сборка мусора в .NET by Andrey Akinshin
Сборка мусора в .NETСборка мусора в .NET
Сборка мусора в .NET
Andrey Akinshin3.9K views

Об особенностях использования значимых типов в .NET

  • 1. Об особенностях использования значимых типов в .NET Андрей Акиньшин Барнаульское сообщество .NET разработчиков bug.ineta.ru www.facebook.com/groups/dotnetbarnaul/
  • 2. Структуры • • • • • Копирование по значению Поддержка boxed и unboxed формы Всегда инициализированы Методы из Equals, GetHashCode из System.ValueType Не могут быть базовыми типами
  • 3. Изменяемые значимые типы public struct Point { public int X, Y; public void Move(int dx, int dy) { X += dx; Y += dy; } } public class Circle { public Point Center; // Поле } var circle = new Circle(); circle.Center = new Point { X = 0, Y = 0 }; circle.Center.Move(5, 5); Console.WriteLine(circle.Center.X);
  • 4. Изменяемые значимые типы public struct Point { public int X, Y; public void Move(int dx, int dy) { X += dx; Y += dy; } } public class Circle { public Point Center { get; set; } // Свойство } var circle = new Circle(); circle.Center = new Point { X = 0, Y = 0 }; circle.Center.Move(5, 5); Console.WriteLine(circle.Center.X);
  • 5. Изменяемые значимые типы Будут проблемы: // 1. Property public class Circle { public Point Center { get; set; } } // 2. Readonly field public class Circle { public readonly Point Center = new Point(); } // 3. IList var points = new List<Point>();
  • 6. Изменяемые значимые типы public struct Enumerator : IEnumerator<T>, IDisposable, IEnumerator var x = new { Items = new List<int> { 1, 2, 3 }.GetEnumerator() }; while (x.Items.MoveNext()) Console.WriteLine(x.Items.Current);
  • 7. Изменяемые значимые типы struct Disposable : IDisposable { public bool Disposed { get; private set; } public void Dispose() { Disposed = true; } } var d = new Disposable(); using (d) { // Some code } Console.WriteLine(d.Disposed);
  • 8. Упаковка и распаковка // 1 var arrayList = new ArrayList(); var p = new Point(); arrayList.Add(p); // Упаковка p = (Point) arrayList[0]; // Распаковка
  • 9. Упаковка и распаковка // 1 var arrayList = new ArrayList(); var p = new Point(); arrayList.Add(p); // Упаковка p = (Point) arrayList[0]; // Распаковка // 2 Int32 x = 5; Object o = x; // Упаковка Int16 y = (Int16) o; // InvalidCastException Int16 z = (Int16)(Int32) o; // Распаковка и приведение
  • 10. Упаковка и распаковка // 1 var arrayList = new ArrayList(); var p = new Point(); arrayList.Add(p); // Упаковка p = (Point) arrayList[0]; // Распаковка // 2 Int32 x = 5; Object o = x; // Упаковка Int16 y = (Int16) o; // InvalidCastException Int16 z = (Int16)(Int32) o; // Распаковка и приведение // 3 Int32 x = 1; Object y = x; x = 2; Console.WriteLine(x + "/" + (Int32)y);// "2/1"
  • 11. Упаковка и распаковка interface IChangeable { void Change(int x, int y); } struct Point : IChangeable { public int X, Y; public void Change(int x, int y) { X = x; Y = y; } public override string ToString() { return X + "," + Y; } }
  • 12. Упаковка и распаковка var p = new Point {X = 1, Y = 1}; Console.WriteLine(p); p.Change(2, 2); Console.WriteLine(p); Object o = p; Console.WriteLine(o); ((Point) o).Change(3, 3); Console.WriteLine(o); ((IChangeable)p).Change(4, 4); Console.WriteLine(p); ((IChangeable)o).Change(5, 5); Console.WriteLine(o);
  • 13. Конструкторы по умолчанию • .NET поддерживает конструкторы по умолчанию для структур
  • 14. Конструкторы по умолчанию • .NET поддерживает конструкторы по умолчанию для структур • А C# — нет
  • 15. Конструкторы по умолчанию • .NET поддерживает конструкторы по умолчанию для структур • А C# — нет • Но мы всё равно создадим структуру с конструктором по умолчанию, которую назовём MyStruct
  • 16. Конструкторы по умолчанию // Вспомогательные методы static T CreateAsDefault<T>() { return default(T); } static T CreateWithNew<T>() where T : new() { return new T(); } // Вызывается var m = Activator.CreateInstance(typeof(MyStruct)); var m = new MyStruct(); // Не вызывается var m = default(MyStruct); var m = CreateWithNew<MyStruct>(); var m = CreateAsDefault<MyStruct>(); var array = new MyStruct[100];
  • 17. GetHashCode() • Быстрая версия (Структура не имеет ссылочных полей, а между её полями нет свободного места) Используем Xor каждых 4 байта структуры • Медленная версия Используем GetHashCode первого нестатичного поля
  • 18. GetHashCode() var a1 = new KeyValuePair<int, int>(1, 2); var a2 = new KeyValuePair<int, int>(1, 3); Console.WriteLine(a1.GetHashCode()); // 1033533110 Console.WriteLine(a2.GetHashCode()); // 1033533111 var b1 = new KeyValuePair<int, string>(1, "x"); var b2 = new KeyValuePair<int, string>(1, "y"); Console.WriteLine(b1.GetHashCode()); // -1888265882 Console.WriteLine(b2.GetHashCode()); // -1888265882
  • 19. Equals() public override bool Equals (Object obj) { // ... FieldInfo[] thisFields = thisType.GetFields( BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); for (int i=0; i<thisFields.Length; i++) { thisResult = ((RtFieldInfo)thisFields[i]). InternalGetValue(thisObj,false); thatResult = ((RtFieldInfo)thisFields[i]). InternalGetValue(obj, false); if (thisResult == null) { if (thatResult != null) return false; } else if (!thisResult.Equals(thatResult)) return false; } return true; }
  • 20. Equals() var redName = Color.Red; var redArgb = Color.FromArgb(255, 255, 0, 0); Console.WriteLine(redName == redArgb);
  • 21. Equals() var redName = Color.Red; var redArgb = Color.FromArgb(255, 255, 0, 0); Console.WriteLine(redName == redArgb); public struct Color { private readonly long value; private readonly string name; private readonly short knownColor, state; public static bool operator ==(Color left, Color right) { if (left.value == right.value && left.state == right.state && left.knownColor == right.knownColor) { if (left.name == right.name) return true; if (left.name == (object) null || right.name == (object) null) return false; return left.name.Equals(right.name); } return false; } }
  • 22. Размещение в памяти public struct S1 { public byte Byte1; public int Int1; } public struct S2 { public byte Byte1; public byte Byte2; public byte Byte3; public byte Byte4; public int Int1; } Console.WriteLine(Marshal.SizeOf(typeof(S1))); Console.WriteLine(Marshal.SizeOf(typeof(S2)));
  • 23. Размещение в памяти [StructLayout(LayoutKind.Explicit)] struct MyStruct { [FieldOffset(0)] public Int16 Value; [FieldOffset(0)] public Byte LowByte; } var s = new MyStruct(); s.Value = 256 + 100; Console.WriteLine(s.LowByte); // 100
  • 24. Размещение в памяти namespace System.Drawing { public struct Color { /** * Shift count and bit mask for A, R, G, B * components in ARGB mode! */ private const int ARGBAlphaShift = 24; private const int ARGBRedShift = 16; private const int ARGBGreenShift = 8; private const int ARGBBlueShift = 0; /// /// /// /// /// /// /// } } WARNING!!! WARNING!!! WARNING!!! WARNING!!! WARNING!!! WARNING!!! WARNING!!! WARNING!!! We can never change the layout of this class (adding or removing or changing the order of member variables) if you want to be compatible v1.0 version of the runtime This is so that we can push into the runtime a custom marshaller for OLE_COLOR to Color.
  • 26. Блоги • http://msdn.microsoft.com/magazine/ • http://www.rsdn.ru/ • http://blogs.msdn.com/b/ericlippert/ • http://sergeyteplyakov.blogspot.ru/ • http://timyrguev.blogspot.ru/ • http://aakinshin.blogspot.ru/