Простейшая реализация шаблона 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 Ұнайды
Если вам нужно, чтобы вложенные экземпляры имели ссылку на свой контейнер, вам нужно объявить поле для ее хранения и озаботиться ее инициализацией. Работать он будет точно так же, как любой объект, который хочет содержать ссылку на другой.
Коду во вложенном типе разрешено использовать непубличные члены содержащего типа. Однако экземпляр вложенного типа автоматически не получает ссылку на экземпляр содержащего типа.
Листинг 3.92. Закрытый вложенный класс
class Program
{
private static void Main(string[] args)
{
// Запрашиваем библиотеку классов о том, где находится папка
// пользователя Мои Документы
string path =
Environment.GetFolderPath(
Environment.SpecialFolder.MyDocuments);
string[] files = Directory.GetFiles(path);
var comparer = new LengthComparer();
Array.Sort(files, comparer);
foreach (string file in files)
{
Console.WriteLine(file);
}
}
private class LengthComparer : IComparer<string>
{
public int Compare(string x, string y)
{
int diff = x.Length - y.Length;
return diff == 0 ? x.CompareTo(y) : diff;
}
}
}
Если вы не определили неявное преобразование в bool, но определили операторы true и false, C# будет использовать оператор true, если вы используете свой тип в качестве выражения для оператора if, цикла do или while или как выражение условия в цикле for. Однако компилятор предпочитает неявный оператор bool, так что это не главная причина существования операторов true и false.
Операторы неявного преобразования не пишут часто. Это следует делать только в том случае, если вы сможете соответствовать тем же стандартам, что применяются к встроенным повышениям: преобразование всегда должно быть возможным и никогда не должно вызывать исключения. Более того, преобразование не должно преподносить сюрпризы, так как неявные преобразования — это довольно хитрая штука в том смысле, что они позволяют вызывать методы с помощью кода, который не похож на вызов метода. Поэтому, если вы не планируете вводить в заблуждение других разработчиков, используйте неявные преобразования только в тех случаях, в которых их можно трактовать однозначно
Если вы используете ключевое слово implicit вместо explicit, ваше преобразование сможет произойти без необходимого приведения. В главе 2 мы увидели, что некоторые преобразования происходят неявно: в определенных ситуациях C# автоматически повышает числовые типы. Например, вы можете использовать int там, где ожидается long, например в качестве аргумента для метода или в присваивании. Преобразование из int в long всегда будет успешным и никогда не потеряет информацию, поэтому компилятор автоматически генерирует код для выполнения такого преобразования, не требуя явного приведения. Если вы пишете неявные операторы преобразования, компилятор C# будет точно так же молча их применять, позволяя использовать ваш пользовательский тип там, где ожидается какой-то другой.
Я использовал явное ключевое слово explicit, которое означает, что эти преобразования доступны с использованием синтаксиса приведения, как показано в листинге 3.91.
Листинг 3.91. Использование операторов явного преобразования
var c = (Counter) 123;
var v = (int) c;
Листинг 3.90. Операторы преобразования
public static explicit operator int(Counter value)
{
return value._count;
}
public static explicit operator Counter(int value)
{
return new Counter { _count = value };
}
Листинг 3.89. Поддержка других типов операндов
public static Counter operator +(Counter x, int y)
{
return new Counter { _count = x._count + y };
}
public static Counter operator +(int x, Counter y)
{
return new Counter { _count = x + y._count };
}
