Предположим, я спросил вас "что такое возвращаемый тип конкатенации"?Что бы вы сказали?Вероятно, вы бы обернулись и спросили "конкатенация чего?"Конкатенация определяется в символах, строках, последовательностях, каталитических запросах, языках, дискретных конечных автоматах и тысячах других вещей, поэтому возвращаемый тип определяется типом аргументов.Но обычно тип конкатенации является типом аргументов.Не всегда;например, конкатенация двух символов представляет собой строку.Но обычно.
Точно так же вопрос "каков тип оператора!?"полностью зависит от того, что отрицается, и вы не сказали, что отрицаете.Обычно отрицание Т - это еще один Т, но это не обязательно.
Я подозреваю, что вы не задаете правильный вопрос.Я думаю, что вопрос, который вы должны задать, это «каков реалистичный сценарий, в котором вы бы перегружали оператор!»?Пример, который вы привели из книги, ужасен;это не мотивирует, почему автор кода вообще переопределяет оператор.
Вот более реалистичный пример.Предположим, мы жили в мире без обнуляемых типов.Вы можете решить использовать трехзначную логику:
sealed class MyBool
{
private MyBool() {} // No one creates it!
public static MyBool True = new MyBool();
public static MyBool False = new MyBool();
public static MyBool Unknown = new MyBool();
Хорошо, каково правило для отрицания MyBool?True становится False, False становится True, Unknown остается неизвестным:
public static MyBool operator !(MyBool b)
{
if (b == True) return False;
if (b == False) return True;
return Unknown;
}
В этом сценарии тип!оператор MyBool.
Конечно, начиная с C # 2.0 у нас есть трехзначная логика в форме Nullable<bool>
, но вам может потребоваться более сложная логика (или вы можете писать код на C # 1.0).
Труднее придумать разумные примеры ситуаций, в которых отрицание Foo приводит к бару;Возможна ситуация с «монадными» объектами рабочего процесса, когда отрицание объекта данного типа - это объект другого типа, представляющий отложенное выполнение отрицания.