В стандартном List<T> например хранится int version, который инкрементится на каждое действие, изменяющее структуру листа. При создании итератора (а он является внутренним классом листа) ему в приватное поле копируется эта версия, а на MoveNext проверяется, есть ли разница между исходным version и текущим и если есть, то вызывается исключение. Реализация Dispose пустая.
Я тут кстати подумал — это вообще невозможно сделать из-за требований обратной совместимости. Допустим, есть код:
class Base {
public void Foo() {
Console.WriteLine("Base.Foo");
}
}
class Derived : Base {
public new void Foo() {
Console.WriteLine("Derived.Foo");
}
}
и в каком-нибудь методе
Base x = new Derived();
if (x is Derived) {
x.Foo(); // вызываем сокрытый Base.Foo, но только если x - Derived
}
Тогда после введения автокаста эта строчка будет выводить Derived.Foo вместо Base.Foo — изменение уже существующего поведения. Я понимаю, что этот код страшный и не жизненный, но он допустим по спецификации и значит его нельзя ломать. Наличие сокрытия имен в языке делает невозможным существование обратно совместимой реализации того, чего вы хотите.
var myClassX = x as MyClass;
if (myClassX != null) {
myClassX.Foo();
}
Тоже многословно, но без второго каста.
Вы, кстати говоря, пробовали закодить «лютомедленный» подход? Я пробовал и моя реализация (на словаре экшнов) была лишь в 4 раза медленнее цепочки if-else if. Аллокация там лишь одного объекта на всю конструкцию, лямбды — лишь 1 доп. вызов метода. Вы считаете, что такая довольно редкая конструкция не имеет права быть в 4 раза медленнее для удобства? На C# все-таки не для микроконтроллеров пишут и в большинстве мест можно поступиться скоростью выполнения.
Во многих местах можно заменить такую конструкцию посетителем. В общем и целом, мне кажется что большинству эта фича покажется неважной, и вряд ли станут язык/компилятор усложнять ради ее.
Недавно тоже о таком думал, но все же лучше уже свитчи по Type — автокаст это имхо не так явно для читающего код, как свитч. Свитчи, кстати говоря, несложно реализуются и с тем что есть, могут выглядеть как ниже, fluent-ность можно варьировать при желании.
var @switch = new TypeSwitch()
.Case<string>(x => ProcessString(x, ...))
.Case<int>(x => Process(int, ...));
@switch.On(value);
Можно сделать специальный интерфейс для обозначения «у класса реализованы арифметические операторы» или более конкретно для каждого отдельно или более узких групп. Т.к. операторы статические, то такой интерфейс скорее будет пустым и должен иметь поддержку со стороны среды или компилятора. Вообще говоря, подобной магии хватает в дотнете — не думаю, что такая реализация казалась бы слишком костыльной.
Так стоп :) Я имел в виду JIT-компиляцию сгенерированного CIL кода (т.е. компиляцию при запуске приложения), уже после того, как C#-компилятор создаст сборку. На том уровне все по минимуму — метаданные, стэковые команды + валидация. Если туда сахар добавлять, то у вас все .NET приложения будут запускаться/работать медленнее.
Мне кажется, что набор тестов + контракты помогут в подавляющем большинстве случаев. Контракты встраиваются в студию и дополняют статическую проверку кода своим статическим анализатором, который вам отловит огромное количество возможных null.
Также можно делать методы расширений для часто используемых операций на объектах, которые могут быть null (например, вызов ивентов). Или написать структуру-враппер для ссылочных типов, если оно настолько нужно.
Вероятно имелся в виду не только CLR, а еще и CIL вместе с ним. При компиляции CIL проверяются ограничения на дженерики (в спеке есть подробное описание). Так что, по идее, можно спустить вывод типов на уровень CIL.
А вот если несколько функциональных класса реализуют метод с одинаковым именем, то потенциально создаются неприятности с копипастом кода)
Вообще говоря, неймспейсы — это тоже синтаксический сахар сишарпа, в CLR их нету — System.String это полное имя класса и ничего, живем. С одинаковыми именами внутри неймспейса и т.п. Я не сильно рад юзингу статических классов, но и страшного в нем нечего тоже, думаю, нету. Для разрешения конфликта имен наверняка так же можно будет использовать алиасы.
А еще все никак не добавят ограничение дженериков на enum и delegate, плюс protected AND internal вдобавок к текущему protected OR internal, хотя все три фичи есть в CLR.
Мне как любителю дженериков больше всего вывод типа для конструктора generic класса понравилось, тоже думал об этом раньше. Жалко, что не добавляют ограничение для дженериков на параметризованные конструкторы — как было бы здорово where T: new(string) или where T1: new(T2, T3)
и в каком-нибудь методе
Тогда после введения автокаста эта строчка будет выводить Derived.Foo вместо Base.Foo — изменение уже существующего поведения. Я понимаю, что этот код страшный и не жизненный, но он допустим по спецификации и значит его нельзя ломать. Наличие сокрытия имен в языке делает невозможным существование обратно совместимой реализации того, чего вы хотите.
Тоже многословно, но без второго каста.
Вы, кстати говоря, пробовали закодить «лютомедленный» подход? Я пробовал и моя реализация (на словаре экшнов) была лишь в 4 раза медленнее цепочки if-else if. Аллокация там лишь одного объекта на всю конструкцию, лямбды — лишь 1 доп. вызов метода. Вы считаете, что такая довольно редкая конструкция не имеет права быть в 4 раза медленнее для удобства? На C# все-таки не для микроконтроллеров пишут и в большинстве мест можно поступиться скоростью выполнения.
Во многих местах можно заменить такую конструкцию посетителем. В общем и целом, мне кажется что большинству эта фича покажется неважной, и вряд ли станут язык/компилятор усложнять ради ее.
Также можно делать методы расширений для часто используемых операций на объектах, которые могут быть null (например, вызов ивентов). Или написать структуру-враппер для ссылочных типов, если оно настолько нужно.
На стадии компиляции запрещать присваивать nullable в не-nullable или в рантайме эксепшн кидать?
Вообще говоря, неймспейсы — это тоже синтаксический сахар сишарпа, в CLR их нету — System.String это полное имя класса и ничего, живем. С одинаковыми именами внутри неймспейса и т.п. Я не сильно рад юзингу статических классов, но и страшного в нем нечего тоже, думаю, нету. Для разрешения конфликта имен наверняка так же можно будет использовать алиасы.