Re[2]: Optional Value. Уменьшение количества null reference-
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 10.09.10 09:17
Оценка: +1
Здравствуйте, Sinclair, Вы писали:

S>Здравствуйте, Alexander Polyakov, Вы писали:


AP>>Отсюда вывод: не использовать null в качестве возвращаемого значения! То есть набирать на клавиатуре null только:

AP>>Но наша цель более скромная – уменьшить количество null-ов. Кстати, по пунктам a и b еще можно кое-что отвоевать.
S>Не очень понятен смысл неиспользования null-ов. Проблема, я так понимаю, в том, что NRE упадёт слишком поздно?

Проблема в том что NRE вообще упадет.

Рассмотрим код:

var x = Method1().Method2().Method3().Method4();


Если везде возвращаются ref-типы, то каждый из методов может вернуть null.
Можно использовать контракты чтобы доказать что null не вернется.
Но иногда все таки методы возвращают null и это является нормальным поведением, а нас во всей операции интересует только конечный результат, тогда хорошо бы иметь способ описать частичные вычисления (которые могут не вернуть результата). В других языках есть конструкции типа .?, которые возвращают null если выражение слева null, но далеко не всегда есть возможность возвращать null, например если результат — value-type.

Вот и реализуют абстракции типа Option, которые позволяют избежать использования null и водопроводного кода типа:

var x1 = Method1();
if(x1 == null) return null;
var x2 = x1.Method2();
if(x2 == null) return null;
var x3 = x2.Method3();
if(x3 == null) return null;
return x3.Method4();


Но у обоих реализаций, представленных здесь, есть недостаток (Elevate им тоже обладает). Вполне можно написать так:

void Method(Option<T> opt)
{
 //неважно
}

Method(null)


Поэтому от NRE полностью уйти не получится.

Вот еще один пример где Option — структура и код выше уже не компилируется.

public struct Option<T> : IEquatable<Option<T>>
{
    public Option(T value)
    {
        Contract.Requires(value != null);
        this.value = value;
        this.hasValue = true;
    }

    public T Value
    {
        get
        {
            if (this.hasValue)
            {
                return this.value;
            }
            else
            {
                throw new InvalidOperationException("Value is empty");
            }
        }
    }

    public bool HasValue
    {
        get { return this.hasValue; }
    }

    public bool Equals(Option<T> other)
    {
        return (this.hasValue == other.hasValue)
            && (!this.hasValue || EqualityComparer<T>.Default.Equals(this.value, other.value));
    }

    public override bool Equals(object obj)
    {
        if (obj == null || obj.GetType() != this.GetType())
        {
            return false;
        }

        var opt = (Option<T>)obj;

        return Equals(opt);
    }

    public override int GetHashCode()
    {
        return hasValue ? EqualityComparer<T>.Default.GetHashCode(value) : 0;
    }

    T value;
    bool hasValue;


    public static implicit operator Option<T>(T value)
    {
        if (value != null)
        {
            return new Option<T>(value);
        }
        else
        {
            return new Option<T>();
        }
    }

    public static explicit operator T(Option<T> option)
    {
        return option.Value;
    }

    [ContractInvariantMethod]
    void ObjectInvariant()
    {
        Contract.Invariant(!hasValue || value != null);
    }
}

public static class Option
{
    public static Option<T> None<T>()
    {
        return new Option<T>();
    }

    public static Option<T> ToOption<T>(this T value)
    {
        return value;
    }

    public static Option<V> SelectMany<T, V>(this Option<T> value, Func<T, Option<V>> selector)
    {
        Contract.Requires(selector != null);
        return value.HasValue ? selector(value.Value) : None<V>();
    }

    public static Option<V> SelectMany<T, K, V>(this Option<T> value, Func<T, Option<K>> selector, Func<T, K, V> resultSelector)
    {
        Contract.Requires(selector != null);
        Contract.Requires(resultSelector != null);
        return value.SelectMany(left => selector(left).SelectMany(right => resultSelector(left, right).ToOption()));
    }

    public static Option<V> Select<T, V>(this Option<T> value, Func<T, V> selector)
    {
        Contract.Requires(selector != null);
        return value.SelectMany(v => selector(v).ToOption());
    }

    public static Option<T> Where<T>(this Option<T> value, Func<T, bool> predicate)
    {
        Contract.Requires(predicate != null);
        return value.SelectMany(v => predicate(v) ? v.ToOption() : None<T>());
    }

    public static V Process<T, V>(this Option<T> value, Func<T, V> success, Func<V> fail)
    {
        Contract.Requires(success != null);
        Contract.Requires(fail != null);
        return value.HasValue ? success(value.Value) : fail();
    }
}
Re[4]: Optional Value.
От: Alexander Polyakov  
Дата: 10.09.10 09:37
Оценка:
Здравствуйте, Qbit86, Вы писали:

AP>>Метод Select по правилам должен называться SelectMany.

Q>По некоторым другим правилам должен называться и вовсе Bind, евпочя
Конечно это мелочи, но все же сделаю замечание. Мы в рамках C#-а. А здесь правила именования уже выбрали до нас. Монадический метод Bind назвали SelectMany. В частности, на второй перегруженный метод SelectMany завязан query comprehension syntax. Первый SelectMany в query comprehension syntax не участвует, но заменять пару перегруженных методов парой разноименных не очень удобно.
Re[5]: Optional Value. Уменьшение количества null reference-
От: Alexander Polyakov  
Дата: 10.09.10 10:25
Оценка:
Здравствуйте, samius, Вы писали:

S>Ближе собственно тем, что при работе с АТД используется один неполиморфный метод.

Метод с условным оператором внутри заметно лучше полиморфного метода?

S>1. Не нужны эти свойства, если пойти через тест типа аки в ПМ (здесь
Автор: samius
Дата: 09.09.10
).

Да, тест типа выглядит симпатичнее свойства HasValue (по крайней мере, на первый взгляд). Но, к сожалению, в C# это пока недоступно.

AP>>Мои аргументы в пользу варианта из первого поста:

AP>>

    AP>>
  1. ...
    AP>>
  2. В случае если не срабатывает type inference, то для extension метода Process придется явно прописывать значения обоих generic параметров. А если Process является методом интерфейса, то прописывать придется значение только одного generic параметра.
    AP>>
S>2. Можно пример?
var result = optionalValue.Process<IA>(value => new B(), () => new C()); //если метод интерфейса
var result = optionalValue.Process<SomeClass, IA>(value => new B(), () => new C()); //если extension метод

interface IA {}
class B: IA { }
class C: IA { }


Кстати, 3-ий аргумент. Реализации свойств Value и HasValue в обязательном порядке должны быть согласованы: если HasValue возвращает true, то Value не должно кидать исключение. Для демонстрации этой проблемы приведу пример. Отмечу, что пример искусственный, эта же задача решается с помощью двух существующих реализаций IOptionalValue. Но все же. Никто не мешает добавить свою имплементацию интерфейса IOptionalValue, которая будет лезть на web service и брать оттуда значение. Если у интерфейса IOptionalValue всего один метод Process, то все прямолинейно и просто:
class WebServiceOptionalValue: IOptionalValue<DateTime>
{
    public TResult Process<TResult>(Func<DateTime, TResult> existFunc, Func<TResult> notExistFunc)
    {
        DateTime webServiceMethod;
        try
        {
            webServiceMethod = WebServiceMethod();
        }
        catch
        {
            return notExistFunc();
        }
        return existFunc(webServiceMethod);
    }
}
А попробуйте написать реализацию интерфейса с двумя методами :
public interface IOptionalValue<TValue>
{
    TValue Value { get; }
    bool HasValue { get; }
}


S>З.Ы. В некоторых случаях может оказаться удобнее OptionalValue, построенный не на АТД, а на кортеже флага и значения. Такая штука шикарно передается в качестве параметров по умолчанию. Описано у desco.

Спасибо, почитаю.
Re[6]: Optional Value. Уменьшение количества null reference-
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 10.09.10 10:35
Оценка: -1
Здравствуйте, Alexander Polyakov, Вы писали:


AP>Кстати, 3-ий аргумент. Реализации свойств Value и HasValue в обязательном порядке должны быть согласованы: если HasValue возвращает true, то Value не должно кидать исключение. Для демонстрации этой проблемы приведу пример. Отмечу, что пример искусственный, эта же задача решается с помощью двух существующих реализаций IOptionalValue. Но все же. Никто не мешает добавить свою имплементацию интерфейса IOptionalValue, которая будет лезть на web service и брать оттуда значение. Если у интерфейса IOptionalValue всего один метод Process, то все прямолинейно и просто:

AP>
AP>class WebServiceOptionalValue: IOptionalValue<DateTime>
AP>{
AP>    public TResult Process<TResult>(Func<DateTime, TResult> existFunc, Func<TResult> notExistFunc)
AP>    {
AP>        DateTime webServiceMethod;
AP>        try
AP>        {
AP>            webServiceMethod = WebServiceMethod();
AP>        }
AP>        catch
AP>        {
AP>            return notExistFunc();
AP>        }
AP>        return existFunc(webServiceMethod);
AP>    }
AP>}
AP>

А как будет выглядеть композиция таких методов?
Например надо получить от двух сервисов данные, как-то обработать их и отправить третьему.

AP>А попробуйте написать реализацию интерфейса с двумя методами :

А в чем сложность?

public static Option<TResult> SafeWebServiceMethod(this WebService webService, ...)
{
    try
    {
        return  webService.WebServiceMethod(...);
    }
    catch
    {
        return Option.None<TResult>;
    }
}
Re[6]: Optional Value. Уменьшение количества null reference-
От: samius Япония http://sams-tricks.blogspot.com
Дата: 10.09.10 10:49
Оценка:
Здравствуйте, Alexander Polyakov, Вы писали:

AP>Здравствуйте, samius, Вы писали:


S>>Ближе собственно тем, что при работе с АТД используется один неполиморфный метод.

AP>Метод с условным оператором внутри заметно лучше полиморфного метода?
Да, т.к. расширять иерархию нет надобности.

S>>1. Не нужны эти свойства, если пойти через тест типа аки в ПМ (здесь
Автор: samius
Дата: 09.09.10
).

AP>Да, тест типа выглядит симпатичнее свойства HasValue (по крайней мере, на первый взгляд). Но, к сожалению, в C# это пока недоступно.
Разве оператор is пока недоступен?

S>>2. Можно пример?

AP>
AP>var result = optionalValue.Process<IA>(value => new B(), () => new C()); //если метод интерфейса
AP>var result = optionalValue.Process<SomeClass, IA>(value => new B(), () => new C()); //если extension метод

AP>interface IA {}
AP>class B: IA { }
AP>class C: IA { }
AP>


решается через Process(value => (IA) new B(), () => (IA) new C());

AP>Кстати, 3-ий аргумент. Реализации свойств Value и HasValue в обязательном порядке должны быть согласованы: если HasValue возвращает true, то Value не должно кидать исключение. Для демонстрации этой проблемы приведу пример.

Я как раз и не настаиваю на наличии Value и HasValue.

AP>Отмечу, что пример искусственный, эта же задача решается с помощью двух существующих реализаций IOptionalValue. Но все же. Никто не мешает добавить свою имплементацию интерфейса IOptionalValue, которая будет лезть на web service и брать оттуда значение. Если у интерфейса IOptionalValue всего один метод Process, то все прямолинейно и просто:


AP>А попробуйте написать реализацию интерфейса с двумя методами :

Здесь я как раз предпочитаю чистый АТД, в том виде, в котором его например моделирует F#. Лишние реализации исключены.
Re[2]: Optional Value. Уменьшение количества null reference-
От: Alexander Polyakov  
Дата: 10.09.10 10:56
Оценка:
Здравствуйте, Sinix, Вы писали:

AP>>Хочется иметь такую технику кодирования, чтобы Extract Method не переводил ошибки компиляции в ошибки run time-а.

S>Правильное решение этой проблемы — использование контрактов и статической верификации. Если бы оно ешё работало...
Называть неработающее решение правильным как-то странно .

S>... использование контрактов и статической верификации. ...

Ага, можно использовать, а можно не использовать. То есть это является дополнением. И следовательно, это менее практично. С OptionValue ситуация другая, оно предлагает замену null-ам, а не дополнение. Почувствуйте разницу .

S>Да. Но, вместо того, чтобы решать проблему в её источнике — методе ...

Источник проблемы всегда в методе? Странное утверждение. Из него следует, что optional логика имеет право имплементироваться только внутри одного метода. Это бред.

AP>> оба варианта ведут себя одинаково -- если код компилируется, то он работает.

S>Да. Но, вместо того, чтобы решать проблему в её источнике — методе, вы передаёте ответственность по соблюдению контракта всему остальному коду. NullReferenceException хотя бы гарантировал, что при ошибке в вашем коде программа упадёт. OptionalValue маскирует исходную проблему и источник её возникновения: "ой, у нас тут значения нет — фиг с ним, подсунем что-нить"
Странная у тебя логика, указания статического верификатора контрактов ты уважаешь, а на сообщения старого доброго компилятора реагируешь как “фиг с ним, подсунем что-нить”.
Re[3]: Optional Value. Уменьшение количества null reference-
От: Andrei N.Sobchuck Украина www.smalltalk.ru
Дата: 10.09.10 11:15
Оценка:
Здравствуйте, Alexander Polyakov, Вы писали:

AP>Скорее нет, чем да. Если пользоваться описаниями ссылка1, ссылка2, то Null Object Pattern предлагает делать кастомный интерфейс и кастомную реализацию Null Object-а для каждого случая. A OptionalValue один для всех .


Один или много объектов — это особенности реализации. См. Smalltalk, Objective-C.
Я ненавижу Hibernate
Автор: Andrei N.Sobchuck
Дата: 08.01.08
!
Re[4]: Optional Value. Уменьшение количества null reference-
От: Alexander Polyakov  
Дата: 10.09.10 11:19
Оценка:
Здравствуйте, gandjustas, Вы писали:

G>Приведи пример где ковариантность необходима.

G>...
G>Приведи пример где ковариантность необходима.
Ты вообще программируешь? Очень странно слышать такой вопрос от практикующего программиста.
Возьми любую задачу, где есть полиморфизм, например, пусть имеются типы TBase, TSubtype1 и TSubtype2. Добавь в эту задачу optional логику. Переменные исходных типов заменятся на IOptionalValue<TBase>, IOptionalValue<TSubtype1> и IOptionalValue<TSubtype2>. Если нет ковариантности, то метод с параметром IOptionalValue<TBase> не сможет принять объект типа IOptionalValue<TSubtype1>.
Re[5]: Optional Value. Уменьшение количества null reference-
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 10.09.10 11:22
Оценка:
Здравствуйте, Alexander Polyakov, Вы писали:

AP>Здравствуйте, gandjustas, Вы писали:


G>>Приведи пример где ковариантность необходима.

G>>...
G>>Приведи пример где ковариантность необходима.
AP>Ты вообще программируешь? Очень странно слышать такой вопрос от практикующего программиста.
Вообще да.

AP>Возьми любую задачу, где есть полиморфизм, например, пусть имеются типы TBase, TSubtype1 и TSubtype2. Добавь в эту задачу optional логику. Переменные исходных типов заменятся на IOptionalValue<TBase>, IOptionalValue<TSubtype1> и IOptionalValue<TSubtype2>. Если нет ковариантности, то метод с параметром IOptionalValue<TBase> не сможет принять объект типа IOptionalValue<TSubtype1>.

Вот меня и интересует конкретный практический пример где такое нужно, а то в моей практике не встречалось.
Re[6]: Optional Value. Уменьшение количества null reference-
От: Alexander Polyakov  
Дата: 10.09.10 11:42
Оценка:
Здравствуйте, gandjustas, Вы писали:

AP>>Возьми любую задачу, где есть полиморфизм, например, пусть имеются типы TBase, TSubtype1 и TSubtype2. Добавь в эту задачу optional логику. Переменные исходных типов заменятся на IOptionalValue<TBase>, IOptionalValue<TSubtype1> и IOptionalValue<TSubtype2>. Если нет ковариантности, то метод с параметром IOptionalValue<TBase> не сможет принять объект типа IOptionalValue<TSubtype1>.

G>Вот меня и интересует конкретный практический пример где такое нужно, а то в моей практике не встречалось.
В моей встречались. Сейчас мне влом поднимать контекст конкретных задач, и вспоминать детали.
Re[7]: Optional Value. Уменьшение количества null reference-
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 10.09.10 11:51
Оценка:
Здравствуйте, Alexander Polyakov, Вы писали:

AP>Здравствуйте, gandjustas, Вы писали:


AP>>>Возьми любую задачу, где есть полиморфизм, например, пусть имеются типы TBase, TSubtype1 и TSubtype2. Добавь в эту задачу optional логику. Переменные исходных типов заменятся на IOptionalValue<TBase>, IOptionalValue<TSubtype1> и IOptionalValue<TSubtype2>. Если нет ковариантности, то метод с параметром IOptionalValue<TBase> не сможет принять объект типа IOptionalValue<TSubtype1>.

G>>Вот меня и интересует конкретный практический пример где такое нужно, а то в моей практике не встречалось.
AP>В моей встречались. Сейчас мне влом поднимать контекст конкретных задач, и вспоминать детали.

То есть не так часто встречались чтобы это было значительным преимуществом для Option.
Re[7]: Optional Value. Уменьшение количества null reference-
От: Alexander Polyakov  
Дата: 10.09.10 12:06
Оценка:
Здравствуйте, samius, Вы писали:

S>>>Ближе собственно тем, что при работе с АТД используется один неполиморфный метод.

AP>>Метод с условным оператором внутри заметно лучше полиморфного метода?
S>Да, т.к. расширять иерархию нет надобности.
Не вижу как этот аргумент позволяет выделить “лучшего” в исходном утверждении. Оно показывает лишь то, что условный оператор может оказаться не хуже.

S>>>1. Не нужны эти свойства, если пойти через тест типа аки в ПМ (здесь
Автор: samius
Дата: 09.09.10
).

AP>>Да, тест типа выглядит симпатичнее свойства HasValue (по крайней мере, на первый взгляд). Но, к сожалению, в C# это пока недоступно.
S>Разве оператор is пока недоступен?
Если это обычный C#-вский оператор “is”, то твоя идея сводится к реализации метода HasValue(). У тебя не будет HasValue в базовом интерфейсе, а будет extention метод HasValue(). Опять таки, не вижу существенной разницы между полиморфным свойством и extention методом. А поскольку из-за желания ковариантности мы не может запретить создание других реализаций, то завязка на типы классов не очень хорошая идея.
Re[8]: Optional Value. Уменьшение количества null reference-
От: Alexander Polyakov  
Дата: 10.09.10 12:09
Оценка: -1
Здравствуйте, gandjustas, Вы писали:

AP>>>>Возьми любую задачу, где есть полиморфизм, например, пусть имеются типы TBase, TSubtype1 и TSubtype2. Добавь в эту задачу optional логику. Переменные исходных типов заменятся на IOptionalValue<TBase>, IOptionalValue<TSubtype1> и IOptionalValue<TSubtype2>. Если нет ковариантности, то метод с параметром IOptionalValue<TBase> не сможет принять объект типа IOptionalValue<TSubtype1>.

G>>>Вот меня и интересует конкретный практический пример где такое нужно, а то в моей практике не встречалось.
AP>>В моей встречались. Сейчас мне влом поднимать контекст конкретных задач, и вспоминать детали.
G>То есть не так часто встречались чтобы это было значительным преимуществом для Option.
Вывод не верный. Экзамен по элементарной логике не сдан, приходите в следующий раз .
Re[8]: Optional Value. Уменьшение количества null reference-
От: samius Япония http://sams-tricks.blogspot.com
Дата: 10.09.10 12:17
Оценка:
Здравствуйте, Alexander Polyakov, Вы писали:

AP>Здравствуйте, samius, Вы писали:


S>>>>Ближе собственно тем, что при работе с АТД используется один неполиморфный метод.

AP>>>Метод с условным оператором внутри заметно лучше полиморфного метода?
S>>Да, т.к. расширять иерархию нет надобности.
AP>Не вижу как этот аргумент позволяет выделить “лучшего” в исходном утверждении. Оно показывает лишь то, что условный оператор может оказаться не хуже.
на мой вкус — лучше в конкретном случае. Навязывать и убеждать не собираюсь.

AP>>>Да, тест типа выглядит симпатичнее свойства HasValue (по крайней мере, на первый взгляд). Но, к сожалению, в C# это пока недоступно.

S>>Разве оператор is пока недоступен?
AP>Если это обычный C#-вский оператор “is”, то твоя идея сводится к реализации метода HasValue().
Сводится. Только зачем ее сводить?

AP>У тебя не будет HasValue в базовом интерфейсе, а будет extention метод HasValue().

Для чего он нужен?

AP>Опять таки, не вижу существенной разницы между полиморфным свойством и extention методом.

Полиморфное свойство не нужно.

AP>А поскольку из-за желания ковариантности мы не может запретить создание других реализаций, то завязка на типы классов не очень хорошая идея.

Другие реализации не нужны. Но запретить тебе их желать я не могу.
Re[4]: Optional Value. Уменьшение количества null reference-
От: Alexander Polyakov  
Дата: 10.09.10 12:27
Оценка:
Здравствуйте, gandjustas, Вы писали:

G>>>Проблема этого интерфейса что он не энфорсит контракт, это при том что кроме Some\Just и None реализаций не нужно. Но я могу сколько угодно своих реализаций подсовывать.

AP>>Это замечание незначительно само по себе,
G>Да ну? Сломать контракт это фигня?
Какой контракт? Ты вообще о чем? Нет у меня никакого контракта. Ломать нечего!

G>>>Но я могу сколько угодно своих реализаций подсовывать.

Пожалуйста подсовывай, мой код будет корректно работать.
Re[9]: Optional Value. Уменьшение количества null reference-
От: Alexander Polyakov  
Дата: 10.09.10 12:30
Оценка:
Здравствуйте, samius, Вы писали:

AP>>А поскольку из-за желания ковариантности мы не может запретить создание других реализаций, то завязка на типы классов не очень хорошая идея.

S>Другие реализации не нужны. Но запретить тебе их желать я не могу.
Мне они тоже не нужны. Мое желание -- иметь ковариантность.
Re[4]: Optional Value. Уменьшение количества null reference-
От: Alexander Polyakov  
Дата: 10.09.10 13:10
Оценка:
Здравствуйте, Andrei N.Sobchuck, Вы писали:

AP>>Скорее нет, чем да. Если пользоваться описаниями ссылка1, ссылка2, то Null Object Pattern предлагает делать кастомный интерфейс и кастомную реализацию Null Object-а для каждого случая. A OptionalValue один для всех .

ANS>Один или много объектов — это особенности реализации. См. Smalltalk, Objective-C.
А вот и нет.
Читаем статью по ссылке:

"[Одним из] недостатков является то, что паттерн 'Null Object' ... приводит к взрывному росту числа классов. Потому что необходимо создать свой 'пустой' класс для каждого абстрактного класса."

О чем я и говорил выше.

Статья про "A Generalized Null Object Pattern". Это другой паттерн.

Я не знаком с Smalltalk и Objective-C, поэтому мне сложно оценить схожесть описанного в статье решения с OptionalValue. Но там идет речь о каком-то:

"Поедающий" сообщения nil

OptionalValue ничего не поедает, поэтому, возможно, статья о другом.
Re[5]: Optional Value. Уменьшение количества null reference-
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 10.09.10 13:12
Оценка:
Здравствуйте, Alexander Polyakov, Вы писали:

AP>Здравствуйте, gandjustas, Вы писали:


G>>>>Проблема этого интерфейса что он не энфорсит контракт, это при том что кроме Some\Just и None реализаций не нужно. Но я могу сколько угодно своих реализаций подсовывать.

AP>>>Это замечание незначительно само по себе,
G>>Да ну? Сломать контракт это фигня?
AP>Какой контракт? Ты вообще о чем? Нет у меня никакого контракта. Ломать нечего!


G>>>>Но я могу сколько угодно своих реализаций подсовывать.

AP>Пожалуйста подсовывай, мой код будет корректно работать.
Твой — будет, а все вместе — нет.
Re[6]: Optional Value. Уменьшение количества null reference-
От: Alexander Polyakov  
Дата: 10.09.10 13:18
Оценка:
Здравствуйте, gandjustas, Вы писали:

G>>>>>Проблема этого интерфейса что он не энфорсит контракт, это при том что кроме Some\Just и None реализаций не нужно. Но я могу сколько угодно своих реализаций подсовывать.

AP>>>>Это замечание незначительно само по себе,
G>>>Да ну? Сломать контракт это фигня?
AP>>Какой контракт? Ты вообще о чем? Нет у меня никакого контракта. Ломать нечего!
G>
Что тебя так рассмешило?

G>... а все вместе — нет.

Код в студию.
Re[10]: Optional Value. Уменьшение количества null reference
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 10.09.10 13:25
Оценка:
Здравствуйте, Alexander Polyakov, Вы писали:

AP>Здравствуйте, samius, Вы писали:


AP>>>А поскольку из-за желания ковариантности мы не может запретить создание других реализаций, то завязка на типы классов не очень хорошая идея.

S>>Другие реализации не нужны. Но запретить тебе их желать я не могу.
AP>Мне они тоже не нужны. Мое желание -- иметь ковариантность.

Ну ты же начал доказывать что ковариантность всем ой как нужна. А на деле не нужна.
Я собственно и до .NET4 не испытывал проблем из-за отсутствия ковариантности интерфейсов, где надо проделывал приведение типа ручками.

Для делегатов вариантность гораздо более существенна.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.