2015-01-26 14 views
18

Quando si tenta di utilizzare la parola chiave C# "come" su un tipo non generico a cui non è possibile eseguire il cast, il compilatore dà un errore che il tipo non può essere convertito.Comportamento in conflitto durante la compilazione utilizzando come parola chiave i tipi generici in C#

Tuttavia quando si utilizza il "come" parola chiave nei confronti di un tipo generico il compilatore dà nessun errore:

public class Foo { } 

public class Bar<T> { } 

public class Usage<T> { 
    public void Test() { 
     EventArgs args = new EventArgs(); 
     var foo = args as Foo;  // Compiler Error: cannot convert type 
     var bar = args as Bar<T>; // No compiler error 
    } 
} 

ho scoperto questo comportamento in una base di codice molto più grande dove la mancanza di un errore di compilazione ha portato a un problema in fase di runtime.

Il comportamento in conflitto è di progettazione? In tal caso, qualcuno ha qualche idea del perché?

+1

FYI: R # fa la bandiera con l'avvertenza "getto sospetto: non v'è alcun tipo nella soluzione che è ereditato sia da "EventArgs" che da "Bar " " – juharr

+0

@juharr grazie! Immagino che vada a dimostrare che il problema è rilevabile in C#. Ho anche ricontrollato il problema con il compilatore F # che come R # preleva il cast non valido (ma nel caso di F # è contrassegnato come errore) –

risposta

8

In §7.10.11 The as operator C# 5.0 specifiche dicono:

In an operation of the form E as T, E must be an expression and T must be a reference type, a type parameter known to be a reference type, or a nullable type. Furthermore, at least one of the following must be true, or otherwise a compile-time error occurs:

  • An identity (§6.1.1), implicit nullable (§6.1.4), implicit reference (§6.1.6), boxing (§6.1.7), explicit nullable (§6.2.3), explicit reference (§6.2.4), or unboxing (§6.2.5) conversion exists from E to T.

  • The type of E or T is an open type.

  • E is the null literal.

Così args as Foo dà un errore, perché niente di tutto questo è vero. Ma nel secondo caso, Bar<T> è un tipo aperto, e la specifica spiega tipo aperto come, §4.4.2 Open and closed types:

An open type is a type that involves type parameters. More specifically:

  • A type parameter defines an open type. [...]
+1

L'ho appena trovato nelle specifiche, ma non sono sicuro di cosa rende speciale un tipo aperto in questo caso. –

+0

grazie! Questo risponde alla domanda "è il comportamento in conflitto di design" con un sì. E la comprensione del perché sembra essere l'ingenua implementazione della traduzione dell'espressione che hai citato dalla documentazione. –

+0

@PhillipTrelford Ho aggiunto qualche spiegazione su questo .. –

-3

"L'operatore as esegue solo conversioni di riferimento, conversioni annullabili e conversioni di boxing. L'operatore as non può eseguire altre conversioni, come le conversioni definite dall'utente, che dovrebbero invece essere eseguite utilizzando le espressioni di trasmissione."

https://msdn.microsoft.com/en-us/library/cscsdfbt.aspx

+3

questo non spiega perché 'args come Bar ' non fornisce alcun compilatore errore. –

Problemi correlati