2010-07-01 19 views
52

A partir de los documentos:Cuál es el punto de "Como" palabra clave en C#

el operador as es como un molde, excepto que produce nula en caso de fallo de conversión en lugar de lanzar una excepción. Más formalmente, una expresión de la forma:

expression as type 

es equivalente a:

expression is type ? (type)expression : (type) null 

la excepción de que la expresión se evalúa sólo una vez.

¿Por qué no elegir o hacerlo de una manera u otra? ¿Por qué tener dos sistemas de casting?

+1

Usted ilegible algo en tu edición: el ejemplo de código se ha ido. – tonio

+4

La mejor parte al respecto ... 'int x = SomeObject as int? ?? 0' – Earlz

+0

Relacionados http://stackoverflow.com/questions/2139798/why-is-the-c-as-operator-so-popular – Jla

Respuesta

76

No son dos sistemas de fundición. Los dos tienen acciones similares pero significados muy diferentes. Un "como" significa "Creo que este objeto podría ser en realidad de este otro tipo; dame nulo si no es así". Un molde significa una de dos cosas:

  • Sé con certeza que este objeto en realidad es de este otro tipo. Haga que sea así, y si me equivoco, bloquee el programa.

  • Sé con certeza que este objeto no es de este otro tipo, pero que hay una forma conocida de convertir el valor del tipo actual al tipo deseado. (Por ejemplo, conversión de int a corto). Haga que sea así, y si la conversión no funciona, bloquee el programa.

Consulte mi artículo sobre el tema para obtener más información.

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

+3

Para los pensadores de C++, 'as' en C# es similar a' dynamic_cast' en C++. – kevinarpe

7

Permite realizar comprobaciones rápidas sin intentos/tara, lo que puede ser necesario en algunos casos para manejar árboles de herencia basados ​​en mensajes.

Lo uso bastante (aparece en un mensaje, reacciona a subtipos específicos). Try/cast podría ser significativamente más lento (muchos intentan/atrapan cuadros en cada mensaje que pasa) - y hablamos de manejar 200,000 mensajes por segundo aquí.

+3

Simplemente curioso si usted o Amber está en lo correcto con respecto a la prueba/captura - suena como ' como 'envuelve la operación en un bloque de prueba, pero tal vez utiliza un mecanismo de conversión más eficiente? – STW

+1

@STW: Estaba pensando lo mismo ... Si tiene su propio try/catch o 'as' tiene su propio try/catch, el rendimiento debería ser comparable. –

+0

Hablando de intentar/echar sobrecarga, echa un vistazo aquí [(con una disculpa del equipo de C#)] (http://stackoverflow.com/a/8947323/227755) – nurettin

11

Porque a veces quieres que las cosas fallen si no puedes lanzar como te espera, y otras veces no te importa y solo quieres descartar un objeto dado si no se puede transmitir.

Es básicamente una versión más rápida de un molde normal envuelto en un bloque try; pero As es mucho más legible y también ahorra tipeo.

+0

Eso explica por qué esta característica existe para el moldeado, pero no por qué tampoco se aplicaría a una docena de otras cosas. A menudo también quiero otras cosas en el lenguaje para regresar silenciosamente nulo, como las búsquedas de diccionario o el análisis enum. ¿Por qué el casting es tan especial? – Ken

+1

El análisis Enum tiene TryParse. –

+2

Los diccionarios y las enumeraciones tienen sus métodos de devolución segura, se llaman TryGetValue y TryParse, respectivamente ... – digEmAll

11

eficiencia y rendimiento

Parte de realizar un reparto integrado es cierta verificación de tipos; así que prefijar el modelo real con una verificación de tipo explícita es redundante (la verificación de tipo se produce dos veces). El uso de la palabra clave as garantiza que solo se realizará una verificación de tipo. Puede pensar "pero tiene que hacer una comprobación nula en lugar de una segunda verificación de tipo", pero la verificación nula es muy eficiente y eficiente en comparación con la verificación de tipo.

if (x is SomeType) 
{ 
    SomeType y = (SomeType)x; 
    // Do something 
} 

hace comprobaciones 2x, mientras que

SomeType y = x as SomeType; 
if (y != null) 
{ 
    // Do something 
} 

hace 1x - el cheque nulo es muy barato en comparación con un tipo de comprobación.

+0

No veo dos comprobaciones en el ejemplo del código anterior. – Dykam

+4

¿Por qué hay un tipo de allí? Eso no tiene ningún sentido. –

+0

@Eric - roger! mi malo, está fuera – STW

2

generalmente elijo uno o el otro basado en la semántica del código.

Por ejemplo, si tiene una object que usted sabe que debe ser un string a continuación, utilizar (string) porque esto expresa que la persona que escribe el código es asegurarse de que el objeto es un string y si no es que ya tenemos grande problemas que la excepción de lanzamiento en tiempo de ejecución que se lanzará.

Utilice as si no está seguro de que el objeto sea de un tipo específico pero desee tener la lógica para cuando es. Puede usar el operador is seguido de un molde, pero el operador as es más eficiente.

0

Tal ejemplos ayudarán:

// Regular casting 
Class1 x = new Class1(); 
Class2 y = (Class2)x; // Throws exception if x doesn't implement or derive from Class2 

// Casting with as 
Class2 y = x as Class2; // Sets y to null if it can't be casted. Does not work with int to short, for example. 

if (y != null) 
{ 
    // We can use y 
} 

// Casting but checking before. 
// Only works when boxing/unboxing or casting to base classes/interfaces 
if (x is Class2) 
{ 
    y = (Class2)x; // Won't fail since we already checked it 
    // Use y 
} 

// Casting with try/catch 
// Works with int to short, for example. Same as "as" 
try 
{ 
    y = (Class2)x; 
    // Use y 
} 
catch (InvalidCastException ex) 
{ 
    // Failed cast 
} 
1

te voy a dar escenarios del mundo real de donde se utilizaría ambos.

public class Foo 
{ 
    private int m_Member; 

    public override bool Equals(object obj) 
    { 
    // We use 'as' because we are not certain of the type. 
    var that = obj as Foo; 
    if (that != null) 
    { 
     return this.m_Member == that.m_Member; 
    } 
    return false; 
    } 
} 

Y ...

public class Program 
{ 
    public static void Main() 
    { 
    var form = new Form(); 
    form.Load += Form_Load; 
    Application.Run(form); 
    } 

    private static void Form_Load(object sender, EventArgs args) 
    { 
    // We use an explicit cast here because we are certain of the type 
    // and we want an exception to be thrown if someone attempts to use 
    // this method in context where sender is not a Form. 
    var form = (Form)sender; 

    } 
} 
Cuestiones relacionadas