Pull to refresh
26
0
Дмитрий @coffeecupwinner

User

Send message
Еще один ход и пойду спать.
В стандартном 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);
Можно сделать специальный интерфейс для обозначения «у класса реализованы арифметические операторы» или более конкретно для каждого отдельно или более узких групп. Т.к. операторы статические, то такой интерфейс скорее будет пустым и должен иметь поддержку со стороны среды или компилятора. Вообще говоря, подобной магии хватает в дотнете — не думаю, что такая реализация казалась бы слишком костыльной.
Можно использовать атрибут Pure из Code Contracts для обозначения константных методов — какая-никакая, да альтернатива.
Так стоп :) Я имел в виду JIT-компиляцию сгенерированного CIL кода (т.е. компиляцию при запуске приложения), уже после того, как C#-компилятор создаст сборку. На том уровне все по минимуму — метаданные, стэковые команды + валидация. Если туда сахар добавлять, то у вас все .NET приложения будут запускаться/работать медленнее.
Мне кажется, что набор тестов + контракты помогут в подавляющем большинстве случаев. Контракты встраиваются в студию и дополняют статическую проверку кода своим статическим анализатором, который вам отловит огромное количество возможных null.

Также можно делать методы расширений для часто используемых операций на объектах, которые могут быть null (например, вызов ивентов). Или написать структуру-враппер для ссылочных типов, если оно настолько нужно.
string myNotSoCoolString = Foo.GetStringOrNull();
string! myCoolString = myNotSoCoolString; // <- что тут должно быть?

На стадии компиляции запрещать присваивать nullable в не-nullable или в рантайме эксепшн кидать?
Вероятно имелся в виду не только CLR, а еще и CIL вместе с ним. При компиляции CIL проверяются ограничения на дженерики (в спеке есть подробное описание). Так что, по идее, можно спустить вывод типов на уровень CIL.
Я встречал «return value as object;», это пока никому не удавалось превзойти :) Перестраховщики, не знающие язык, будут всегда.
А вот если несколько функциональных класса реализуют метод с одинаковым именем, то потенциально создаются неприятности с копипастом кода)

Вообще говоря, неймспейсы — это тоже синтаксический сахар сишарпа, в CLR их нету — System.String это полное имя класса и ничего, живем. С одинаковыми именами внутри неймспейса и т.п. Я не сильно рад юзингу статических классов, но и страшного в нем нечего тоже, думаю, нету. Для разрешения конфликта имен наверняка так же можно будет использовать алиасы.
Вывод типов для дженерик методов сейчас реализован на стороне C# — для конструкторов наверно так же сделают, чтобы зря CIL/CLR не усложнять.
А еще все никак не добавят ограничение дженериков на enum и delegate, плюс protected AND internal вдобавок к текущему protected OR internal, хотя все три фичи есть в CLR.
Мне как любителю дженериков больше всего вывод типа для конструктора generic класса понравилось, тоже думал об этом раньше. Жалко, что не добавляют ограничение для дженериков на параметризованные конструкторы — как было бы здорово where T: new(string) или where T1: new(T2, T3)
А вот это всегда хорошо :)
Об этом я и говорю. Такие вещи, как мне кажется, стоит делать только когда совсем нужны эти 3 числа и улучшить алгоритм не представляется возможным.

Information

Rating
Does not participate
Location
Москва, Москва и Московская обл., Россия
Date of birth
Registered
Activity