2009-10-15 7 views
15

He-nunca-usado as o is en C# o en cualquier otro lenguaje que admita la palabra clave.Un uso real para `as` y` is`

¿Para qué lo usó?

No me refiero a cómo lo uso me refiero a cómo realmente lo necesita?

También me salí con hacer no typecasting en un proyecto de C++ bastante grande (estaba orgulloso).

Teniendo en cuenta que casi nunca mecanografío ¿por qué necesito la palabra clave as o is?

+2

La principal ventaja de "como" es que no arrojará una excepción cuando el lanzamiento no es válido. El tipo de transmisión directa lo haría. –

+3

Depende del significado de lo que es. ;) – kenny

+0

Consulte también "¿Cuándo utilizar información de tipo de tiempo de ejecución?" en http://stackoverflow.com/questions/1520466 – ChrisW

Respuesta

34

Tuve que escribir código para enumerar todos los controles colocados en un formulario web de ASP.NET y realizar ciertas operaciones en controles específicos, p. agrega un color de fondo a todos los cuadros de texto, y así sucesivamente.

La principal ventaja de as y is es que puedo verificar con seguridad si una variable es de un tipo determinado usando is sin que se produzcan excepciones. Una vez que estoy seguro de que es de un tipo determinado, puedo convertirlo de manera fácil y segura al tipo necesario usando as.

Lo que básicamente me (simplificado!) Es un

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

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

y así sucesivamente. Sin as y is esto sería mucho más desordenado, en mi humilde opinión.

Básicamente, es probable que necesite o pueda hacer un buen uso de as y is si está lidiando con polimorfismo mucho - si tiene listas de cosas que pueden ser de cualquier tipo, como controles en una página mi ejemplo Si no tiene o no usa mucho polimorfismo, es poco probable que encuentre la necesidad de esos operadores.

Marc

+4

Es posible que también lonces aquí. Ya ha usado el es para probar su objeto para el tipo correcto. http://blogs.msdn.com/ericlippert/archive/2009/10/08/what-s-the-difference-between-as-and-cast-operators.aspx –

+2

@Matthew: sí podrías ... ¿crees? eso es más fácil/más legible? No lo creo ... –

+0

Si conoces C# no es menos legible. Pero lo hace a menos trabajo. –

1

Los moldes de estilo C (como (Foo)bar) arrojarán InvalidCastException si el molde falla. as, por otro lado, dará null (vea this). El operador is se utiliza para probar si un tipo de instancia en tiempo de ejecución es compatible con el tipo proporcionado (consulte this).

is se utiliza ampliamente en .NET System.ComponentModel namespace. Más específicamente, TypeConverter API depende en gran medida del operador is para determinar cómo convertir de un tipo a otro.

8

Pregunta intrigante. En realidad, los uso todo el tiempo. is es útil para descubrir si un objeto es de cierto tipo, lo uso ocasionalmente en genéricos o en bucles a través de objetos que son de diferentes tipos. También es invaluable con Reflection.

El otro, as encuentra muchos más usos. A menudo es mucho más seguro usar un lanzamiento normal: cuando falla, devuelve un valor nulo, en lugar de una excepción. También encuentro que es una sintaxis más clara y más fácil de usar, verifica el valor de retorno para nulo y luego agrega un bloque de excepción.

Básicamente, lo que quiero decir es, yo prefiero esta:

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 
} 

y esto:

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

en contraposición a esto:

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 
    } 
} 

por supuesto, esto es solo un ejemplo, pero cuando puedo evitar try/catch, lo haré. Esto también deja más espacio para que pasen las excepciones reales.

16

Uso 'como' un atajo útil en controladores de eventos para recuperar el objeto que envía cuando no puedo saber en el momento del diseño al remitente.

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

+1. Muy bueno para reutilizar controladores de eventos, una muy buena práctica. –

+0

gracioso cómo necesitaba tantas palabras para explicar lo mismo. Buen ejemplo! – Abel

+0

No entiendo.Parece que siempre está exceptuando un botón y también ¿en qué caso establecería esto como una devolución de llamada donde el remitente NO es un botón? –

10

Aquí hay una que llega hasta mucho:

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

Esto es un lugar donde "es" sería mejor –

+0

no realmente si necesita continuar en el objeto Foo, usar 'es' siempre implica dos acciones de conversión de reparto (comparación con' es' y fundición), mientras se proyecta una vez y se prueba para null parece un poco más eficiente. Casting, 'as' y' is' están muy optimizados, por lo que en la práctica es simplemente una cuestión de gusto. – Abel

+2

No realmente. Si usa 'is', entonces necesita lanzar a' Foo' para poder hacer la comparación (¡a menos que todos los Foo sean iguales!). –

3

Aquí es un puesto de Eric Lippert describe cómo "como" se utiliza en C#:

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

utilizo como todo el tiempo. Cuando tengo que retirar un objeto serializado de la memoria caché de la sesión, lo uso para determinar si el objeto serializado está allí y del tipo correcto.Puedo evitar que el programa arroje un error, usando el operador as y buscando null. Si es nulo, sé que falta algo, y puedo volver a crear el objeto y volver a insertarlo en la memoria caché para la próxima vez que lo necesite.

Puede lograr el mismo resultado utilizando el operador de conversión, pero eso agrega la sobrecarga de una excepción, especialmente cuando sabe que el objeto serializado no estará allí parte del tiempo.

+0

+1 para Eric Lippert :) –

2

C# oferta manera de modelo utilizando el IS y como operador. El operador is comprueba si un objeto es compatible con un tipo determinado, y el resultado de la evaluación es un booleano: verdadero o falso. El operador is nunca lanzará una excepción. El código siguiente muestra:

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. 

Si la referencia de objeto es nulo, el operador es siempre devuelve falso, porque no hay ningún objeto disponibles para comprobar su tipo.

El es operador se utiliza típicamente como sigue:

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

En este código, el CLR es en realidad la comprobación de tipos del objeto en dos ocasiones: el es el primer operador comprueba para ver si o es compatible con el tipo de empleado . Si es así, dentro de la declaración if, el CLR verifica nuevamente que o se refiere a un empleado cuando realiza el reparto.

C# ofrece una manera de simplificar el código y mejorar su rendimiento al proporcionar una como operador:

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

En este código, los cheques CLR si o es compatible con el tipo de empleado, y si es , como devuelve un puntero no nulo al mismo objeto. Si o no es compatible con el tipo Empleado, entonces el operador as devuelve nulo.

1

Utilicé ambas palabras clave extensamente en una aplicación de WinForms donde hay una GUI para editar una factura, cada fila en el ListView podría contener diferentes tipos de elementos (es decir, podría ser una línea de pedido o una descripción, o ...) Todos los elementos que puse en el ListView se derivaron de ListViewItem, entonces más adelante cuando fui a implementar cosas como editar el elemento seleccionado, tuve que verificar qué tipo de elemento fue seleccionado (usando is) para mostrar la GUI de edición apropiada.

+0

también es un buen ejemplo –

2

Si alguna vez se desarrolla en un proyecto que ofrece una interfaz de complementos a continuación as y is se convierten rápidamente en sus MUY mejores amigos.

7

Lo uso para obtener datos de manera limpia de DataReader que podría ser DBNull.

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

o

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

+1 esp. el segundo caso encuentra muchos usos con tipos anulables, ¡genial para incluirlo aquí! – Abel

+0

MUY buen uso. ¡Marcaría esto también si pudiera tener más de uno! : / –

2

Aquí hay otro caso de uso para entrar en el gabinete del Dr. Caligari ;-)

Usted puede encadenar el operador as, como en:

x = obj as Label as Control; 

¿Por qué harías tal cosa? Si quiere nulo si no es una etiqueta, pero quiere tratarlos a todos como control. Simplemente enviar Textbox y Label directamente a Control arrojaría éxito para ambos, ahora será nulo para los tipos de Control no deseados. Este es un método abreviado que no necesitará con frecuencia, pero que ocasionalmente es útil.

Un uso alternativo para el mismo es cuando necesita ToString() en un objeto, pero solo cuando es del tipo correcto, de lo contrario, desea una cadena por defecto. Este es un escenario que encuentro muy a menudo, esp. con POCOs Debido ToString() es virtual, esto funciona:

// 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

Si realmente no tener que hacer la colada entonces es probable que no tendría mucho uso para estos operadores. En mi experiencia, sin embargo, la programación de .NET requiere mucha conversión, especialmente cuando se trata con delegados donde los argumentos se proporcionan tipeados como 'objeto'. Creo que la introducción de los genéricos ha ayudado a reducir la necesidad del casting, pero ciertamente es algo que utilizo bastante a menudo. Podría estar "haciéndolo mal", pero esa ha sido mi experiencia.

Así que si vas a hacer casting de todos modos me gusta mucho el operador 'es' para una mejor legibilidad del código. Prefiero miro

if(foo is SomeType) {...} 

continuación

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

TypeConverters encargo viene a la mente primero.

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); 
     } 

segundo proviene de un caso en el que tengo una sombra de un objeto (por cambios de seguimiento) que se hereda de una clase base

respuesta
class BaseClass 
{ 
    BaseClass _shadow; 
} 

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

marc_s 's es un poco defectuoso , Veo este código todo el tiempo, así que quiero enfatizar la importancia de la diferencia entre estos operadores. is es una prueba booleana para determinar si un objeto es asignable a un tipo determinado. as comprueba si un objeto es asignable a un tipo determinado y, si lo es, devuelve ese objeto como ese tipo; si no, devuelve nulo. respuesta marc_s 's realmente está haciendo este

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); 
} 

Es redundante utilizar is con as. Cuando utilice as simplemente reemplácelo con la expresión anterior, es equivalente. Use is con moldes directos () o as solo. Una mejor forma de escribir ese ejemplo sería.

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 si te gusta mucho 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 ejemplo del mundo real que me encuentro con todo el tiempo es cada vez más objetos de un área de almacenamiento que sólo volver tipo de objeto. El almacenamiento en caché es un gran ejemplo.

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

utilizo as mucho menos en código real, ya que realmente sólo funciona para los tipos de referencia. Considere el siguiente código

int x = o as int; 

if (x != null) 
    ??? 

as falla debido a un int no puede ser nulo. is funciona bien, aunque

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

Estoy seguro de que hay también una cierta diferencia de velocidad entre estos operadores, pero para una aplicación real, la diferencia es insignificante.