Создание значимых мероприятий международного масштаба в России
Об особенностях использования значимых типов в .NET
-
Upload
andrey-akinshin -
Category
Education
-
view
2.281 -
download
3
Transcript of Об особенностях использования значимых типов в .NET
![Page 1: Об особенностях использования значимых типов в .NET](https://reader036.fdocuments.net/reader036/viewer/2022081603/55a1d9c01a28abf2198b4606/html5/thumbnails/1.jpg)
Об особенностях использования значимых типов в .NET
Андрей Акиньшин
Барнаульское сообщество .NET разработчиков
bug.ineta.ruwww.facebook.com/groups/dotnetbarnaul/
![Page 2: Об особенностях использования значимых типов в .NET](https://reader036.fdocuments.net/reader036/viewer/2022081603/55a1d9c01a28abf2198b4606/html5/thumbnails/2.jpg)
Структуры
• Копирование по значению• Поддержка boxed и unboxed формы• Всегда инициализированы• Методы из Equals, GetHashCode из System.ValueType• Не могут быть базовыми типами
![Page 3: Об особенностях использования значимых типов в .NET](https://reader036.fdocuments.net/reader036/viewer/2022081603/55a1d9c01a28abf2198b4606/html5/thumbnails/3.jpg)
Изменяемые значимые типы
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);
![Page 4: Об особенностях использования значимых типов в .NET](https://reader036.fdocuments.net/reader036/viewer/2022081603/55a1d9c01a28abf2198b4606/html5/thumbnails/4.jpg)
Изменяемые значимые типы
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);
![Page 5: Об особенностях использования значимых типов в .NET](https://reader036.fdocuments.net/reader036/viewer/2022081603/55a1d9c01a28abf2198b4606/html5/thumbnails/5.jpg)
Изменяемые значимые типы
Будут проблемы:// 1. Propertypublic class Circle{
public Point Center { get; set; }}// 2. Readonly fieldpublic class Circle{
public readonly Point Center = new Point();}// 3. IListvar points = new List<Point>();
![Page 6: Об особенностях использования значимых типов в .NET](https://reader036.fdocuments.net/reader036/viewer/2022081603/55a1d9c01a28abf2198b4606/html5/thumbnails/6.jpg)
Изменяемые значимые типы
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);
![Page 7: Об особенностях использования значимых типов в .NET](https://reader036.fdocuments.net/reader036/viewer/2022081603/55a1d9c01a28abf2198b4606/html5/thumbnails/7.jpg)
Изменяемые значимые типы
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);
![Page 8: Об особенностях использования значимых типов в .NET](https://reader036.fdocuments.net/reader036/viewer/2022081603/55a1d9c01a28abf2198b4606/html5/thumbnails/8.jpg)
Упаковка и распаковка
// 1var arrayList = new ArrayList();var p = new Point();arrayList.Add(p); // Упаковкаp = (Point) arrayList[0]; // Распаковка
// 2Int32 x = 5;Object o = x; // УпаковкаInt16 y = (Int16) o; // InvalidCastExceptionInt16 z = (Int16)(Int32) o; // Распаковка и приведение
// 3Int32 x = 1;Object y = x;x = 2;Console.WriteLine(x + "/" + (Int32)y);// "2/1"
![Page 9: Об особенностях использования значимых типов в .NET](https://reader036.fdocuments.net/reader036/viewer/2022081603/55a1d9c01a28abf2198b4606/html5/thumbnails/9.jpg)
Упаковка и распаковка
// 1var arrayList = new ArrayList();var p = new Point();arrayList.Add(p); // Упаковкаp = (Point) arrayList[0]; // Распаковка
// 2Int32 x = 5;Object o = x; // УпаковкаInt16 y = (Int16) o; // InvalidCastExceptionInt16 z = (Int16)(Int32) o; // Распаковка и приведение
// 3Int32 x = 1;Object y = x;x = 2;Console.WriteLine(x + "/" + (Int32)y);// "2/1"
![Page 10: Об особенностях использования значимых типов в .NET](https://reader036.fdocuments.net/reader036/viewer/2022081603/55a1d9c01a28abf2198b4606/html5/thumbnails/10.jpg)
Упаковка и распаковка
// 1var arrayList = new ArrayList();var p = new Point();arrayList.Add(p); // Упаковкаp = (Point) arrayList[0]; // Распаковка
// 2Int32 x = 5;Object o = x; // УпаковкаInt16 y = (Int16) o; // InvalidCastExceptionInt16 z = (Int16)(Int32) o; // Распаковка и приведение
// 3Int32 x = 1;Object y = x;x = 2;Console.WriteLine(x + "/" + (Int32)y);// "2/1"
![Page 11: Об особенностях использования значимых типов в .NET](https://reader036.fdocuments.net/reader036/viewer/2022081603/55a1d9c01a28abf2198b4606/html5/thumbnails/11.jpg)
Упаковка и распаковка
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;}
}
![Page 12: Об особенностях использования значимых типов в .NET](https://reader036.fdocuments.net/reader036/viewer/2022081603/55a1d9c01a28abf2198b4606/html5/thumbnails/12.jpg)
Упаковка и распаковка
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);
![Page 13: Об особенностях использования значимых типов в .NET](https://reader036.fdocuments.net/reader036/viewer/2022081603/55a1d9c01a28abf2198b4606/html5/thumbnails/13.jpg)
Конструкторы по умолчанию
• .NET поддерживает конструкторы по умолчанию дляструктур
• А C# — нет• Но мы всё равно создадим структуру с конструкторомпо умолчанию, которую назовём MyStruct
![Page 14: Об особенностях использования значимых типов в .NET](https://reader036.fdocuments.net/reader036/viewer/2022081603/55a1d9c01a28abf2198b4606/html5/thumbnails/14.jpg)
Конструкторы по умолчанию
• .NET поддерживает конструкторы по умолчанию дляструктур
• А C# — нет
• Но мы всё равно создадим структуру с конструкторомпо умолчанию, которую назовём MyStruct
![Page 15: Об особенностях использования значимых типов в .NET](https://reader036.fdocuments.net/reader036/viewer/2022081603/55a1d9c01a28abf2198b4606/html5/thumbnails/15.jpg)
Конструкторы по умолчанию
• .NET поддерживает конструкторы по умолчанию дляструктур
• А C# — нет• Но мы всё равно создадим структуру с конструкторомпо умолчанию, которую назовём MyStruct
![Page 16: Об особенностях использования значимых типов в .NET](https://reader036.fdocuments.net/reader036/viewer/2022081603/55a1d9c01a28abf2198b4606/html5/thumbnails/16.jpg)
Конструкторы по умолчанию
// Вспомогательные методы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];
![Page 17: Об особенностях использования значимых типов в .NET](https://reader036.fdocuments.net/reader036/viewer/2022081603/55a1d9c01a28abf2198b4606/html5/thumbnails/17.jpg)
GetHashCode()
• Быстрая версия(Структура не имеет ссылочных полей, а между еёполями нет свободного места)Используем Xor каждых 4 байта структуры
• Медленная версияИспользуем GetHashCode первого нестатичного поля
![Page 18: Об особенностях использования значимых типов в .NET](https://reader036.fdocuments.net/reader036/viewer/2022081603/55a1d9c01a28abf2198b4606/html5/thumbnails/18.jpg)
GetHashCode()
var a1 = new KeyValuePair<int, int>(1, 2);var a2 = new KeyValuePair<int, int>(1, 3);Console.WriteLine(a1.GetHashCode()); // 1033533110Console.WriteLine(a2.GetHashCode()); // 1033533111
var b1 = new KeyValuePair<int, string>(1, "x");var b2 = new KeyValuePair<int, string>(1, "y");Console.WriteLine(b1.GetHashCode()); // -1888265882Console.WriteLine(b2.GetHashCode()); // -1888265882
![Page 19: Об особенностях использования значимых типов в .NET](https://reader036.fdocuments.net/reader036/viewer/2022081603/55a1d9c01a28abf2198b4606/html5/thumbnails/19.jpg)
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;
}
![Page 20: Об особенностях использования значимых типов в .NET](https://reader036.fdocuments.net/reader036/viewer/2022081603/55a1d9c01a28abf2198b4606/html5/thumbnails/20.jpg)
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;
}}
![Page 21: Об особенностях использования значимых типов в .NET](https://reader036.fdocuments.net/reader036/viewer/2022081603/55a1d9c01a28abf2198b4606/html5/thumbnails/21.jpg)
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;
}}
![Page 22: Об особенностях использования значимых типов в .NET](https://reader036.fdocuments.net/reader036/viewer/2022081603/55a1d9c01a28abf2198b4606/html5/thumbnails/22.jpg)
Размещение в памяти
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)));
![Page 23: Об особенностях использования значимых типов в .NET](https://reader036.fdocuments.net/reader036/viewer/2022081603/55a1d9c01a28abf2198b4606/html5/thumbnails/23.jpg)
Размещение в памяти
[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
![Page 24: Об особенностях использования значимых типов в .NET](https://reader036.fdocuments.net/reader036/viewer/2022081603/55a1d9c01a28abf2198b4606/html5/thumbnails/24.jpg)
Размещение в памяти
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.
}}
![Page 25: Об особенностях использования значимых типов в .NET](https://reader036.fdocuments.net/reader036/viewer/2022081603/55a1d9c01a28abf2198b4606/html5/thumbnails/25.jpg)
Хорошие книжки
![Page 26: Об особенностях использования значимых типов в .NET](https://reader036.fdocuments.net/reader036/viewer/2022081603/55a1d9c01a28abf2198b4606/html5/thumbnails/26.jpg)
Блоги
• 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/
![Page 27: Об особенностях использования значимых типов в .NET](https://reader036.fdocuments.net/reader036/viewer/2022081603/55a1d9c01a28abf2198b4606/html5/thumbnails/27.jpg)
Спасибо за внимание!