Вопрос

Есть ли что-то не так с использованием неявного оператора, как следующее:

//linqpad c# program example
void Main()
{
    var testObject = new MyClass<int>() { Value = 1 };

    var add = 10 + testObject; //implicit conversion to int here
    add.Dump(); // 11
}

class MyClass<T>
{
    public T Value { get; set; }
    public static implicit operator T (MyClass<T> myClassToConvert)
    {
        return myClassToConvert.Value;
    }
}

Я думал, что я мог бы относиться к примеру объекта в качестве значения такого типа, но видя, как я никогда не видел пример этого, я думал, может быть, была причина нет сделать что-то подобное, что кто-то мог указать?

В моем фактическом коде я думал о том, чтобы сделать это как часть слоя абстракции данных, чтобы я мог бы вернуть объекты с информацией, описывающей основные данные, но позволяют логическому коду обрабатывать его в качестве типа, когда все его необходимо знать Это значение, и в то же время сохраняйте все это здорово и введите безопасным с двоиками.

Это было полезно?

Решение

Если все следующие верны:

  • все Возможные значения вашего MyClass<T> Тип (в том числе null Если это не тип значения!) Карта допустимого значения T

  • неявный оператор никогда не бросает (даже не для null!)

  • Неявное преобразование делает семантический смысл и не путает клиентский программист

Тогда в этом нет ничего плохого. Конечно ты мог Делайте любую из этих трех вещей, но это был бы плохой дизайн. В частности, неявный оператор, который бросает, может быть очень трудно отладить, потому что место, где он называется, не говорит о том, что он называется.

Например, считайте, что T? не имеет неявного преобразования в T (куда T Это, конечно, тип значения). Если бы был такой неявный оператор, это пришлось бы бросить, когда T? это ноль, так как нет очевидной ценности для преобразования null чтобы это имело бы смысл для Любые тип ценности T.


Позвольте мне привести пример, где у меня были проблемы с отладкой вопроса, где бросил неявный оператор:

public string Foo()
{
    return some_condition ? GetSomething() : null;
}

Здесь, GetSomething вернул что-то из типов, который я написал, который имеет пользовательское неявное преобразование в string. Отказ я сделал Абсолютно уверен тот GetSomething никогда не мог вернуться null, и все же я получил NullReferenceExceptionДействительно Почему? Потому что вышеуказанный код нет эквивалентно

return some_condition ? (string)GetSomething() : (string)null;

но

return (string)(some_condition ? GetSomething() : (Something)null);

Теперь вы можете увидеть, где null пришли из!

Другие советы

Это отличный узор. Просто имейте в виду, что для того, чтобы использовать его как переменную типа T, вы должны либо явно бросить его T, или назначить его переменной типа T. Отказ Катушка будет проходить автоматически в вызовах метода и другие вещи (например, ваш пример дополнения), который принимает T.

Неявное преобразование без назначения?

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top