Pregunta

¿Hay algo malo con el uso de un operador implícita como la siguiente:

//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;
    }
}

Yo estaba pensando que podía tratar como instancia del objeto como un valor de tipo de esta manera, pero ya que nunca he visto un ejemplo de esto pensé que tal vez había una razón no para hacer algo como esto que alguien podría señalar?

En mi código real que estaba pensando en hacer esto como parte de una capa de abstracción de datos, de modo que pudiera devolver objetos con información que describe los datos subyacentes, pero permitir que el código de la lógica a tratarlo como un tipo de valor cuando todo lo que necesita a conocer es el valor, y al mismo tiempo mantener todo tipo agradable y seguro con los genéricos.

¿Fue útil?

Solución

Si todos los siguientes son verdaderas:

  • todos posibles valores de su tipo MyClass<T> (incluyendo null si no es un tipo de valor!) Asignar a un valor válido de T

  • el operador implícito nunca tira (ni siquiera por null!)

  • la conversión implícita tiene sentido semántico y no se confunde con el programador del cliente

entonces no hay nada de malo en esto. Por supuesto que podría hace cualquiera de estas tres cosas, pero sería un mal diseño. En particular, un operador implícito de que la lanza puede ser muy difíciles de depurar porque el lugar donde se le llama no dice que se está llamando.

Por ejemplo, considere que T? no tiene ninguna conversión implícita a T (donde T es, por supuesto, un tipo de valor). Si había dicho operador implícita, tendría que tirar cuando el T? es nulo, ya que no hay un valor obvio a null convertido a eso tendría sentido para cualquier valor de tipo T.


Déjenme darles un ejemplo en el que tuve problemas para depurar un problema donde el operador implícito Lanza:

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

A continuación, GetSomething devuelto algo de un tipo que escribí que tiene una conversión implícita definida por el usuario a string. Hice absolutamente seguro que GetSomething nunca podría volver null, y sin embargo me dieron una NullReferenceException! ¿Por qué? Debido a que el código anterior es no equivalente a

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

pero a

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

Ahora usted puede ver donde el null vino!

Otros consejos

Esto es un gran modelo. Hemos de tener en cuenta que con el fin de utilizarlo como una variable de tipo T, tienen que desechar, ya sea de forma explícita a T, o asignarlo a una variable de tipo T. El reparto se llevará a cabo de forma automática en las llamadas a métodos y otras cosas (como el ejemplo de la suma) que tienen un T.

conversión implícita sin asignación?

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top