2010-09-29 6 views
8

Y at-il de mal à utiliser un opérateur implicite comme ce qui suit:opérateur implicite sur les types génériques

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

Je pensais que je pouvais traiter comme exemple de l'objet en tant que type de valeur de cette façon, mais en voyant que je Je n'ai jamais vu un exemple de ceci, je pensais qu'il y avait peut-être une raison pour faire quelque chose comme ça que quelqu'un pourrait le faire remarquer? Dans mon code actuel, je pensais faire cela dans le cadre d'une couche d'abstraction de données, de sorte que je puisse retourner des objets avec des informations décrivant les données sous-jacentes, mais permettre au code logique de le traiter comme un type de valeur. a besoin de savoir est la valeur, et en même temps, gardez-le tout beau et tapez en toute sécurité avec les génériques.

Répondre

10

Si toutes les conditions suivantes sont remplies:

  • toutes valeurs possibles de votre type MyClass<T> (y compris null si ce n'est pas un type de valeur!) Carte à une valeur valide de T

  • l'opérateur implicite ne lève jamais (pas même pour null!)

  • le co implicite nVersion sens sémantique et n'est pas source de confusion pour le programmeur client

alors il n'y a rien de mal à cela. Bien sûr, pourrait faire l'une de ces trois choses, mais ce serait une mauvaise conception. En particulier, un opérateur implicite qui lance peut être très difficile à déboguer car l'endroit où il est appelé ne dit pas qu'il est appelé.

Par exemple, considérons que T? n'a pas de conversion implicite en T (où T est, bien sûr, un type de valeur). S'il y avait un tel opérateur implicite, il devrait jeter lorsque le T? est nul, car il n'y a pas de valeur évidente pour convertir null à ce qui aurait un sens pour valeur type T.


Permettez-moi de donner un exemple où j'ai eu du mal à le débogage d'un problème où l'opérateur implicite lancé:

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

Ici, GetSomething retourné quelque chose d'un type que j'ai écrit qui a une conversion implicite définie par l'utilisateur à string. J'ai fait absolument sûr que GetSomething ne pourrait jamais retourner null, et pourtant j'ai obtenu un NullReferenceException! Pourquoi? Parce que le code ci-dessus est pas équivalent à

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

mais

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

Maintenant vous pouvez voir où l'null vient!

+0

Je ne suis pas sûr que je comprends l'inquiétude autour de types nullables ... Il me semble que si vous aviez n = new MyClass () {valeur} = null; et le code consommateur a tenté de faire quelque chose comme int i = n; et il jetterait la même exception que toute mauvaise distribution, rien de spécial sur le type nullable ici non? – asawyer

+0

@asawyer: C'était juste un exemple. Imaginez qu'il n'y ait pas de 'T? 'Et que * vous * deviez implémenter un' 'Nullable ' '. Souhaitez-vous lui donner une conversion implicite en 'T'? Ma réponse explique pourquoi vous ne devriez pas, et pourquoi le * réel * 'T?' Ne le fait pas. – Timwi

+0

Je vois maintenant, ce sont ces types de préoccupations qui ont provoqué la question en premier lieu. Il semble que je devrais être autorisé à procéder, mais soyez très prudent. – asawyer

1

C'est un bon modèle. Gardez juste à l'esprit que pour l'utiliser comme une variable de type T, vous devez le convertir explicitement en T, ou l'affecter à une variable de type T. La conversion aura lieu automatiquement dans les appels de méthode et d'autres choses (comme votre exemple d'addition) qui prennent un T.

Implicit conversion without assignment?

+0

Ce n'est pas vrai. – Timwi

+0

@Timwi, êtes-vous sûr? 'MyClass myClass', à ce stade,' myClass. * 'Ne résoudra que les membres sur 'MyClass ', pas sur' T'. Vous auriez à faire comme mentions arootbeer, et faire '((T) myClass). *' Afin d'accéder à tous les membres sur 'T' lui-même. –

+0

J'ai posé cette même question il y a quelques jours. http://stackoverflow.com/questions/3703555/implicit-conversion-without-assignment – arootbeer

Questions connexes