2009-08-11 6 views
5

prendere questo esempio:Var tipo parola inferenza ambiguità quando entrambi interfaccia e implementazione sono presenti

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    

    } 
} 

Nell'esempio precedente, qual è il tipo di prodotto? È IEntity o prodotto? Sembra che il prodotto sia di tipo implementazione concreta (prodotto). Se questo è il caso, non var dovrebbe essere usato solo in circostanze particolari. Ma vedo che strumenti come il resharper raccomandano l'uso di var di default. Non dovrebbe un programma per un'interfaccia?

risposta

1

var product = new Product() è di tipo Product. È possibile programmare sull'interfaccia se non si utilizzano membri esterni all'interfaccia (Product.Count non si trova nell'interfaccia IEntity).

Aggiunto:

Inoltre, in VS2008, è possibile sorvolare la parola chiave var nella dichiarazione per vedere il tipo implicita. Questo messaggio hover/tooltip funziona anche sul nome della variabile dopo la riga di dichiarazione. (da C# In Depth, pagina 211)

+0

Il punto è, la variabile "prodotto" sarà sempre predefinita per tipo di "Prodotto" (piuttosto che IEntity) indipendentemente da se la classe implementata (Prodotto) ha membri aggiuntivi, quando si utilizza var. – Mank

+0

È possibile creare un'interfaccia 'IProduct' che includa i membri aggiunti da' Product'. – ironsam

0

Se si utilizza var in questa istanza, sarà di tipo Product. Non mi piace l'utilizzo di var per impostazione predefinita, in quanto può rendere il codice di lettura un po 'confuso, a volte.

Preferisco utilizzare var principalmente nelle query LINQ, ma cercare di non utilizzarlo in altri luoghi (come nell'esempio). Per le persone che usano un IDE con intellisense va bene, ma se stai leggendo il codice con Notepad (o Notepad ++, ecc.), Avrai più difficoltà a capire il tipo senza una piccola ricerca.

+0

Questo è il mio punto di vista. Infatti, nel mio esempio, questo è l'unico modo per programmare l'interfaccia. – Mank

+0

Quindi sì, come ho detto, non lo userei in queste circostanze. Lo uso principalmente solo per le query LINQ. – mkchandler

6

Che cosa succede se si ha un prodotto come ...

class Product : IFirst, ISecond, IThrid 

L'unica cosa razionale il compilatore può fare è quello che fa. Non limito il mio uso di var, lo uso ovunque. Penso che renda il codice molto più leggibile. In questo caso, sono d'accordo con ReSharper su tutta la linea.

7

Non si sta effettivamente "programmando su interfacce" se si sta ancora creando un'istanza della classe concreta all'interno del metodo, poiché la dipendenza dalla classe di prodotto concreta rimane ancora. Per poter programmare correttamente le interfacce è necessario rimuovere la nuova istanza, ad esempio utilizzando una fabbrica o IoC.

4

Se si desidera Product essere di tipo IEntity, provate questo:

var product = new Product() as IEntity; 

Detto questo, sì, si dovrebbe programmare a un'interfaccia, ma nel tuo caso il gioco è un'istanza del tipo concreto direttamente. Se hai già creato una dipendenza dal tipo concreto, usa solo il tipo concreto. In caso contrario, utilizzare una fabbrica o un'iniezione per ottenere un'istanza dell'interfaccia. var funzionerà con quelli piuttosto bene. Per esempio:

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

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

Infine, no, non credo var dovrebbe essere utilizzato solo in "circostanze particolari". Lo trovo abbastanza utile e lo uso quasi sempre.

+0

come viene utilizzato per la trasmissione senza eccezioni. Dovrebbe essere var product = (IEntity) new Product(); – cbuteau

1

Il tipo che viene dedotto è il tipo effettivo, non una qualsiasi interfaccia o classe base che può implementare/ereditare.

Considerate questo:

var answer = "42"; 

Se sarebbe inferire un'interfaccia piuttosto che il tipo, il tipo di variabile sarebbe qualcosa di simile IComparable invece di string.

L'utilizzo della parola chiave var si basa su di esso inferendo il tipo effettivo o non avrebbe senso utilizzarlo per qualcosa di diverso dai tipi anonimi. Finché il tipo è ovvio puoi usarlo per rendere il codice più leggibile, ma se il tipo non è completamente ovvio, dovresti evitare di usarlo. (Il mio esempio sopra è nell'area grigia, in quanto in realtà non contiene il nome del tipo string.)

Problemi correlati