2009-10-15 10 views
15

Non ho mai usato as o is in C# o qualsiasi lingua che supporta la parola chiave.Un uso reale per `as` e` is`

Per cosa l'hai usato?

Non voglio dire come lo uso, cioè come ne hai effettivamente bisogno?

Sono anche riuscito a fare no typecasting in un progetto C++ piuttosto grande (ero orgoglioso).

Quindi, considerando che non ho quasi mai typecast perché ho bisogno della parola chiave as o is?

+2

Il vantaggio principale di "come" è che non sarà un'eccezione quando cast è valido. Cast diretto tipo sarebbe. –

+3

Dipende dal significato di come è. ;) – kenny

+0

Vedere anche "Quando utilizzare le informazioni sul tipo di runtime?" a http://stackoverflow.com/questions/1520466 – ChrisW

risposta

34

Ho dovuto scrivere codice per enumerare su tutti i controlli posizionati su un Webform ASP.NET ed eseguire determinate operazioni su controlli specifici, ad es. aggiungi un colore di sfondo a tutte le caselle di testo e così via.

Il vantaggio principale di as e is per me è che posso controllare, senza rischi se una variabile è di un certo tipo utilizzando is senza eccezioni accadendo. Una volta che sono sicuro che sia di un certo tipo, posso tranquillamente e facilmente convertirlo nel tipo necessario usando as.

Quello che ho praticamente fatto (semplificato!) È un

foreach(Control c in form.Controls) 
{ 
    if(c is Textbox) 
     HandleTextbox(c as Textbox); 

    if(c is Listbox) 
     HandleListbox(c as Listbox); 
} 

e così via. Senza as e is questo sarebbe molto più confuso, IMHO.

Fondamentalmente, probabilmente avrai bisogno o puoi fare un buon uso di as e is se hai a che fare con il polimorfismo molto - se hai elenchi di cose che possono essere un numero qualsiasi di tipi, come i controlli su una pagina in il mio esempio Se non si dispone o non si utilizza molto il polimorfismo, è improbabile che si verifichi la necessità di tali operatori.

Marc

+4

Si potrebbe anche cast qui. Hai già usato il test per il tuo oggetto per il tipo corretto. http://blogs.msdn.com/ericlippert/archive/2009/10/08/what-s-the-difference-between-as-and-cast-operators.aspx –

+2

@Matthew: sì, potresti - pensi è più facile/più leggibile? Io non la penso così ... –

+0

Se conosci C# non è meno leggibile. Ma lo fa per meno lavoro. –

1

I modelli in stile C (come (Foo)bar) generano InvalidCastException se il cast fallisce. as, d'altra parte, produrrà null (vedi this). L'operatore is viene utilizzato solo per verificare se un tipo di esecuzione dell'istanza data è compatibile con il tipo fornito (vedere this).

is viene utilizzato estesamente nello spazio dei nomi.NET System.ComponentModel. Più specificamente, l'API TypeConverter fa molto affidamento sull'operatore is per determinare come convertire da un tipo all'altro.

8

Domanda intrigante. In realtà, li uso sempre. is è utile per scoprire se un oggetto è di un certo tipo, lo uso occasionalmente in generici o in loop attraverso oggetti di diverso tipo. È anche inestimabile con Reflection.

L'altro, as trova molti altri usi. Spesso è molto più sicuro usare un cast normale: quando fallisce, restituisce null, invece di un'eccezione. Trovo anche la sintassi più chiara e più facile da usare, controllare il valore di ritorno per null, quindi aggiungere un blocco di eccezioni.

In sostanza, quello che intendo dire è, preferisco questo:

protected void GeneralEventHandler(object sender, EventArgs e) 
{ 
    Button btn = sender as Button; 
    if(btn != null) // click came from a button! 
     // do something 
    else 
     // other cases 
} 

e questo:

protected void GeneralEventHandler(object sender, EventArgs e) 
{ 
    if(sender is Button) // click came from a button! 
     // do something 
    else 
     // other cases 
} 

in contrapposizione a questo:

protected void GeneralEventHandler(object sender, EventArgs e) 
{ 
    try 
    { 
     Button btn = (Button) sender; 
     // if we get this far, it's a button 
    } 
    catch(InvalidCastException ice) 
    { 
     // click did not come from a button! Handle other cases 
    } 
} 

naturalmente, questo è solo un esempio, ma quando posso evitare try/catch, lo farò. Questo lascia anche spazio a reali eccezioni da superare.

16

Uso 'as' come un pratico collegamento nei gestori di eventi per richiamare l'oggetto di invio quando non posso sapere in fase di progettazione il mittente.

protected void SomeButtonInAGridView_Click(object sender, EventArgs e) 
{ 
    Button clickedButton = sender as Button; 
} 
+2

+1. Ottimo per riutilizzare i gestori di eventi, un'ottima pratica. –

+0

divertente come avevo bisogno di tante più parole per spiegare lo stesso. Bel esempio! – Abel

+0

Non capisco.Sembra che tu stia sempre eccetto un pulsante e anche in questo caso lo imposteresti come un callback in cui il mittente NON è un pulsante? –

10

Ecco uno che viene in su un sacco:

class Foo { 
    public override bool Equals(object obj) 
    { 
     // The more specific function needs to do null checking anyway. 
     return Equals(obj as Foo); 
    } 

    public bool Equals(Foo obj) 
    { 
     // do some comparison here. 
    } 
} 
+0

Questo è un punto in cui "è" sarebbe meglio –

+0

non proprio se è necessario continuare sull'oggetto Foo, l'uso di 'is' implica sempre due azioni di conversione cast (confronto con' is' e casting), mentre si esegue il cast una volta e il test per null sembra leggermente più efficiente. Il cast, 'as' e' is' sono altamente ottimizzati, quindi in pratica è semplicemente una questione di gusti. – Abel

+2

Non proprio. Se usi 'is', allora devi lanciare a' Foo' per poter fare il confronto (a meno che tutti i Foo non siano uguali!). –

3

Ecco un post di Eric Lippert che descrive come "come" viene utilizzato in C#:

http://blogs.msdn.com/ericlippert/archive/2009/10/08/what-s-the-difference-between-as-and-cast-operators.aspx

uso come tutto il tempo. Quando devo estrarre un oggetto serializzato dalla cache di sessione, lo uso per determinare se l'oggetto serializzato è lì e del tipo giusto.Posso evitare che il programma lanci un errore, usando l'operatore as e controllando null. Se è nulla, so che manca qualcosa e posso ricreare l'oggetto e reinserirlo nella cache per la prossima volta che ne ho bisogno.

È possibile ottenere lo stesso risultato utilizzando l'operatore di trasmissione, ma questo aggiunge l'overhead di un'eccezione, specialmente quando si sa che l'oggetto serializzato non sarà parte del tempo.

+0

+1 per Eric Lippert :) –

2

C# offerta modo per lanciare con la IS e in qualità di operatore. L'operatore is controlla se un oggetto è compatibile con un determinato tipo e il risultato della valutazione è un booleano: vero o falso. L'operatore is non genererà mai un'eccezione. Il codice seguente dimostra:

System.Object o = new System.Object(); 
System.Boolean b1 = (o is System.Object); // b1 is true. 
System.Boolean b2 = (o is Employee); // b2 is false. 

Se il riferimento all'oggetto è nullo, l'operatore is restituisce sempre falso perché non c'è oggetto presente per verificare il tipo.

L'operatore is è tipicamente utilizzata come segue:

if (o is Employee) { 
Employee e = (Employee) o; 
// Use e within the ‘if’ statement. 
} 

In questo codice, il CLR è in realtà controllando il tipo di oggetto due volte: l'operatore is controlla innanzitutto per vedere se o è compatibile con il tipo Dipendente . Se lo è, quindi all'interno dell'istruzione if, il CLR verifica nuovamente che o si riferisca a un Dipendente quando esegue il cast.

C# offre un modo per semplificare il codice e migliorare le sue prestazioni, fornendo una qualità di operatore:

Employee e = o as Employee; 
if (e != null) { 
// Use e within the ‘if’ statement. 
} 

In questo codice, il CLR controlla se o è compatibile con il tipo Employee, e se è , come restituisce un puntatore non nullo allo stesso oggetto. Se o non è compatibile con il tipo Dipendente, l'operatore as restituisce null.

1

Ho utilizzato entrambe le parole chiave in un'app WinForms in cui è presente una GUI per modificare una fattura, ogni riga nello ListView potrebbe contenere diversi tipi di elementi (ad esempio, potrebbe essere un elemento pubblicitario o una descrizione o ...). Tutti gli articoli che ho messo nel ListView sono stati derivati ​​da ListViewItem, così poi più tardi quando sono andato a implementare cose come la modifica della voce selezionata, ho dovuto verificare quale tipo di elemento selezionato (usando is) per mostrare la GUI di modifica appropriata.

+0

anche un buon esempio –

2

Se mai sviluppa su un progetto che offre un'interfaccia plug-in poi as e is diventeranno rapidamente i tuoi MOLTO migliori amici.

7

Lo uso per ottenere in modo pulito i dati da DataReader che potrebbe essere DBNull.

int? personHeight = dr["Height"] as int?; 

o

int personHeight = dr["Height"] as int? ?? 0; 
+0

+1 esp. il secondo caso trova molti usi con tipi nullable, ottimo per includerlo qui! – Abel

+0

MOLTO buon uso. Segnerei anche questo corretto se potessi averne più di uno! : / –

2

Ecco un altro caso d'uso per entrare nel gabinetto del dottor Caligari ;-)

È possibile concatenare il as dell'operatore, come in:

x = obj as Label as Control; 

Perché dovresti fare una cosa del genere? Se vuoi null se non è un'etichetta, ma vuoi trattarli tutti come Control. Il semplice casting di Textbox e Label direttamente su Control avrebbe avuto successo per entrambi, ora sarà nullo per i tipi di controllo indesiderati. Questo è un metodo di scelta rapida che non è necessario spesso, ma a volte è a portata di mano.

Un utilizzo alternativo per lo stesso è quando è necessario ToString() su un oggetto, ma solo quando è del tipo corretto, altrimenti si desidera una stringa predefinita. Questo è uno scenario che incontro molto spesso, esp. con POCOs. Perché ToString() è virtuale, questo funziona:

// assume SomeClass has overridden ToString() 
// return "none" if item is not of type SomeClass or if it is null to begin with 
string itemText = (item as SomeClass as Object ?? "none").ToString(); 
0

Se sei veramente non dover mai fare getto allora io probabilmente non avrei avuto molto uso per questi operatori. Nella mia esperienza, tuttavia, la programmazione .NET richiede un sacco di cast soprattutto quando si tratta di delegati in cui gli argomenti sono forniti digitati come 'oggetto'. Penso che l'introduzione dei generici abbia contribuito a ridurre il bisogno di casting, ma è certamente qualcosa che uso molto spesso. Potrei "sbagliare" ma è stata solo la mia esperienza.

Quindi, se avete intenzione di fare la fusione in ogni caso mi piace molto la 'è' operatore per una migliore leggibilità del codice. Preferirei mille volte guardo

if(foo is SomeType) {...} 

poi

if(foo.GetType() == typeof(SomeType)) {...} 
1

personalizzate TypeConverters viene prima in mente.

public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value) 
     { 
      if (value is string) 
      { 
       return GetEnumValue(myVal, (string)value); 
      } 
      if (value is Enum) 
      { 
       return GetEnumDescription((Enum)value); 
      } 
      return base.ConvertFrom(context, culture, value); 
     } 

In secondo luogo viene da un caso in cui ho l'ombra di un oggetto (per il rilevamento delle modifiche) che viene ereditato da una classe base

risposta
class BaseClass 
{ 
    BaseClass _shadow; 
} 

protected override void UpdateShadow() 
{ 
    ThisClass shadow = _shadow as ThisClass; 
     //... 
} 
0

s' marc_s è un po' viziato , Vedo questo codice tutto il tempo quindi voglio sottolineare l'importanza della differenza tra questi operatori. is è un test booleano per determinare se un oggetto è assegnabile a un determinato tipo. as controlla se un oggetto è assegnabile a un determinato tipo e, in caso affermativo, restituisce quell'oggetto come tale tipo, in caso contrario restituisce null. risposta marc_s s' è davvero facendo questo

foreach(Control c in form.Controls) 
{ 
    if(c is Textbox) 
     HandleTextbox(c is Textbox ? (Textbox)c : null); 

    if(c is Listbox) 
     HandleListbox(c is Listbox ? (Listbox)c : null); 
} 

È superfluo utilizzare is con as. Quando usi mai as sostituiscilo con l'espressione sopra, è equivalente. Utilizzare is con calchi diretti () o as solo da se stessa. Un modo migliore per scrivere quell'esempio sarebbe.

foreach(Control c in form.Controls) 
{ 
    if(c is Textbox) 
     HandleTextbox((Textbox)c); 
     //c is always guaranteed to be a Textbox here because of is 

    if(c is Listbox) 
     HandleListbox((Listbox)c); 
     //c is always guaranteed to be a Listbox here because of is 
} 

O se vi piace veramente as

foreach(Control c in form.Controls) 
{ 
    var textBox = c as Textbox; 
    if(textBox != null) 
    { 
     HandleTextbox(textBox); 
     continue; 
    } 

    var listBox = c as ListBox 
    if(listBox != null) 
     HandleListbox(listBox); 
} 

Un esempio reale mondo che mi imbatto in tutto il tempo sta ottenendo gli oggetti da una zona di stoccaggio che restituiscono solo tipo di oggetto. Il caching è un ottimo esempio.

Person p; 
if (Cache[key] is Person) 
    p = (Person)Cache[key]; 
else 
    p = new Person(); 

io uso as molto meno nel codice vero e proprio perché funziona davvero solo per i tipi di riferimento. Si consideri il seguente codice

int x = o as int; 

if (x != null) 
    ??? 

as fallisce perché un int non può essere nulla. is funziona bene anche se

int x; 
if (o is int) 
    x = (int)o; 

Sono sicuro che ci sia anche una certa differenza di velocità tra questi operatori, ma per una vera e propria applicazione la differenza è trascurabile.

Problemi correlati