operatore implicito sui tipi generici
-
26-09-2019 - |
Domanda
C'è male niente con l'utilizzo di un operatore implicita come la seguente:
//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;
}
}
stavo pensando che potrei trattare come istanza dell'oggetto come valore tipo in questo modo, ma visto che non ho mai visto un esempio di questo ho pensato che forse c'era un motivo non da fare qualcosa di simile che qualcuno potrebbe indicare?
Nel mio codice vero e stavo pensando di fare questo come parte di un livello di astrazione dati, in modo da poter restituire gli oggetti con le informazioni che descrivono i dati sottostanti, ma permettere al codice della logica di trattarlo come un tipo di valore, quando tutto ciò che serve di conoscere è il valore, e allo stesso tempo tenere tutto bello e il tipo sicuro con i farmaci generici.
Soluzione
Se tutte le seguenti condizioni:
-
tutti possibili valori del vostro tipo
MyClass<T>
(tra cuinull
se non è un tipo di valore!) Mappare un valore valido diT
-
l'operatore implicita mai getta (neanche per
null
!) -
la conversione implicita ha senso semantico e non è fonte di confusione per il programmatore client
allora non c'è niente di sbagliato in questo. Naturalmente si potrebbe fare nessuna di queste tre cose, ma sarebbe cattivo design. In particolare, un operatore implicito che getta può essere molto difficile da eseguire il debug perché il luogo dove è chiamato non dice che si riceve una chiamata.
Ad esempio, si consideri che T?
ha alcuna conversione implicita a T
(dove T
è, naturalmente, un tipo di valore). Se ci fosse un operatore come implicita, avrebbe dovuto gettare quando il T?
è nullo, in quanto non v'è alcun valore ovvio per convertire null
a che avrebbe senso per qualsiasi valore del tipo T
.
Vi faccio un esempio in cui ho avuto problemi di debug un problema in cui l'operatore implicita buttato:
public string Foo()
{
return some_condition ? GetSomething() : null;
}
Qui, GetSomething
restituito qualcosa di un tipo che ho scritto che ha una conversione implicita definito dall'utente a string
. Ho fatto assolutamente sicuri che GetSomething
non potrebbe mai tornare null
, e tuttavia ho ottenuto un NullReferenceException
! Perché? Poiché il codice di cui sopra è non equivalente a
return some_condition ? (string)GetSomething() : (string)null;
ma per
return (string)(some_condition ? GetSomething() : (Something)null);
Ora si può vedere dove la null
è venuto da!
Altri suggerimenti
Questo è un grande modello. Basta tenere a mente che, al fine di utilizzarlo come una variabile di tipo T
, si deve lanciare in modo esplicito a T
, oppure assegnarlo a una variabile di tipo T
. Il cast avrà automaticamente posto in chiamate di metodo e altre cose (come ad esempio il vostro esempio oltre) che accettano un T
.