2009-08-11 4 views
5

Prenez cet exemple:Var inférence de type mot-clé ambiguïté lorsque les deux interface et la mise en œuvre sont présents

interface IEntity { 
    string Name { get; set; } 
} 

class Product : IEntity { 
    public string Name { get; set; } 
    public int Count { get; set; } // added member 
} 

class Client { 
    void Process() { 
     var product = new Product(); 
     int count = product.Count; // this is valid    

    } 
} 

Dans l'exemple ci-dessus, quel est le type de produit? Est-ce IEntity ou produit? Il semble que le produit soit de type implémentation concrète (Produit). Si tel est le cas, var ne devrait pas être utilisé uniquement dans des circonstances particulières. Mais je vois que des outils comme resharper recommandent d'utiliser var par défaut. Ne devrait pas un programme à une interface?

Répondre

1

var product = new Product() est de type Product. Vous pouvez programmer sur l'interface si vous n'utilisez pas de membres en dehors de cette interface (Product.Count n'est pas sur l'interface IEntity).

Ajouté:

En outre, dans VS2008, vous pouvez passer la souris sur le mot-clé var dans la déclaration pour voir le type implicite. Ce message survol/info-bulle fonctionne également sur le nom de la variable après la ligne de déclaration. (de C# In Depth, page 211)

+0

Le point est, la variable "produit" sera toujours par défaut au type de "Produit" (plutôt que IEntity) indépendamment de si la classe implémentée (Product) a des membres supplémentaires, quand on utilise var. – Mank

+0

Vous pouvez créer une interface 'IProduct' qui inclut les membres ajoutés par' Product'. – ironsam

0

Si vous utilisez var dans cette instance, il sera de type Product. Je n'aime pas utiliser var par défaut, car cela peut parfois rendre le code de lecture un peu confus.

Je préfère utiliser var principalement dans les requêtes LINQ, mais essayez de ne pas l'utiliser à d'autres endroits (comme votre exemple). Pour les personnes utilisant un IDE avec intellisense, c'est bien, mais si vous lisez le code avec Notepad (ou Notepad ++, etc.), vous aurez plus de mal à trouver le type sans un peu de recherche.

+0

C'est aussi mon point. Enfait, dans mon exemple, c'est la seule façon de programmer à l'interface. – Mank

+0

Alors oui, comme je l'ai dit, je ne l'utiliserais pas dans ces circonstances. Je l'utilise principalement juste pour les requêtes LINQ. – mkchandler

6

si vous aviez un produit comme ...

class Product : IFirst, ISecond, IThrid 

La seule chose rationnelle la complier peut faire est ce qu'il fait. Je ne limite pas mon utilisation de var, je l'utilise partout. Je pense que cela rend le code beaucoup plus lisible. Dans ce cas, je suis d'accord avec ReSharper dans tous les domaines.

7

Vous n'êtes pas en train de "programmer des interfaces" si vous instanciez toujours la classe concrète dans la méthode, car la dépendance à la classe de produit concrète reste toujours. Pour programmer correctement les interfaces, vous devez supprimer l'instanciation nouvelle, par exemple en utilisant une fabrique ou un IoC.

4

Si vous voulez Product être de type IEntity, essayez ceci:

var product = new Product() as IEntity; 

Cela dit, oui vous devez programmer à une interface, mais dans votre cas, vous êtes instancier le type de béton directement. Si vous avez déjà créé une dépendance au type concret, utilisez simplement le type concret. Sinon, utilisez une fabrique ou une injection pour obtenir une instance de l'interface. var va travailler avec ceux plutôt bien. Par exemple:

public class MyExtremelySimpleFactoryExampleClass 
{ 
    public IEntity Instantiate() 
    { 
    return new Product(); 
    } 
} 

// elsewhere in your code... 
var item = myFactory.Instantiate(); // item is of type IEntity 

Enfin, non, je ne pense pas var devrait être utilisé que dans des « circonstances particulières ». Je trouve cela très utile et je l'utilise presque toujours.

+0

comme est utilisé pour la coulée sans exception. Il devrait être var product = (IEntity) new Product(); – cbuteau

1

Le type déduit est le type réel, pas une interface ou une classe de base qu'il peut implémenter/hériter.

Considérez ceci:

var answer = "42"; 

Si elle conclurait une interface plutôt que le type, le type de variable serait quelque chose comme IComparable au lieu de string.

L'utilisation du mot-clé var repose sur l'inférence du type réel, ou il serait illogique de l'utiliser pour autre chose que des types anonymes. Tant que le type est évident, vous pouvez l'utiliser pour rendre le code plus lisible, mais si le type n'est pas complètement évident, vous devriez éviter de l'utiliser. (Mon exemple ci-dessus est dans la zone grise, car il ne contient pas réellement le nom de type string.)

Questions connexes