Простейшая реализация шаблона await
public class MyAwaitableType
{
public MinimalAwaiter GetAwaiter()
{
return new MinimalAwaiter();
}
public class MinimalAwaiter : INotifyCompletion
{
public bool IsCompleted => true;
public string GetResult() => "This is a result";
public void OnCompleted(Action continuation)
{
throw new NotImplementedException();
}
}
}
1 Ұнайды
# предлагает ключевое слово с похожим на первый взгляд поведением: вы можете определить поле как const. Однако этот вариант предназначен для несколько иных целей. Поле readonly инициализируется, а затем никогда не изменяется, тогда как поле const определяет значение, которое неизменно является одним и тем же.
Компилятор предотвратит случайное изменение поля, но при достаточной решимости вы можете обойти эту защиту. Но даже безо всяких уловок поле readonly может быть изменено в процессе работы конструктора
Ключевое слово readonly не дает никаких гарантий. Существуют механизмы, с помощью которых можно добиться изменения значения поля readonly
также можете применить ключевое слово readonly к полю, и это говорит о том, что оно может быть установлено только во время создания и не может быть изменено после
Ключевое слово readonly гарантирует только то, что любое конкретное значение этого типа не изменится. Если вы хотите перезаписать существующее значение совершенно другим значением, это ваше дело
Обычно C# генерирует код, который на самом деле делает копию, потому что в целом он не может знать, изменится ли struct после вызова какого-либо ее члена. Это называется защитными копиями, и они гарантируют, что подобные выражения не повлекут за собой неприятных сюрпризов, таких как изменение значения свойства или поля, которое должно быть только для чтения. Однако, поскольку Point является readonly struct, компилятору известно, что ему в данном случае не нужно создавать защитную копию. В этом случае компилятор C# или JIT-компилятор (или генератор кода AoT) может безопасно оптимизировать этот код, вызывая DistanceFromOrigin непосредственно для значения, хранящегося в LocationRecord, без предварительного создания копии
Листинг 3.23. Структура только для чтения в свойстве только для чтения
public class LocationRecord
{
public LocationRecord(string label, Point location)
{
Label = label;
Location = location;
}
public string Label { get; }
public Point Location { get; }
}
Во-вторых, структуры только для чтения содержат определенную оптимизацию. Если в каком-либо другом типе вы объявляете поле readonly (напрямую или косвенно с автоматическим свойством только для чтения), тип которого readonly struct, компилятор может избежать копирования данных, когда что-то использует это поле
Листинг 3.22. Структура только для чтения
public readonly struct Point
{
public Point(double x, double y)
{
X = x;
Y = y;
}
public double X { get; }
public double Y { get; }
public double DistanceFromOrigin()
{
return Math.Sqrt(X * X + Y * Y);
}
}
