Tengo una clase Animal
y su subclase Dog
. A menudo me encuentro codificando las siguientes líneas:
if (animal is Dog)
{
Dog dog = animal as Dog;
dog.Name;
...
}
Para la variable Animal animal;
.
¿Hay alguna sintaxis que me permita escribir algo como:
if (Dog dog = animal as Dog)
{
dog.Name;
...
}
c#
casting
if-statement
Miguel
fuente
fuente
bool
condición?null
=false
En C #; C # solo permite bools reales o cosas implícitamente convertibles en bools enif
condiciones. Ni nulos ni ninguno de los tipos enteros son implícitamente convertibles en bools.Respuestas:
La respuesta a continuación se escribió hace años y se actualizó con el tiempo. A partir de C # 7, puede usar la coincidencia de patrones:
Tenga en cuenta que
dog
todavía está dentro del alcance después de laif
declaración, pero definitivamente no está asignado.No, no hay Sin embargo, es más idiomático escribir esto:
Dado que "como seguido por if" casi siempre se usa de esta manera, podría tener más sentido que haya un operador que realice ambas partes de una sola vez. Esto no está actualmente en C # 6, pero puede ser parte de C # 7, si se implementa la propuesta de coincidencia de patrones .
El problema es que no puede declarar una variable en la parte de condición de una
if
instrucción 1 . El enfoque más cercano que se me ocurre es este:Eso es desagradable ... (Acabo de probarlo y funciona. Pero, por favor, no hagas esto. Ah, y puedes declararlo
dog
usando,var
por supuesto).Por supuesto, podrías escribir un método de extensión:
Luego llámalo con:
Alternativamente, puede combinar los dos:
También puede usar un método de extensión sin una expresión lambda de una manera más limpia que el ciclo for:
Luego:
1 Puede asignar valores en las
if
declaraciones, aunque rara vez lo hago. Sin embargo, eso no es lo mismo que declarar variables. No es terriblemente inusual que lo haga en un momentowhile
cuando leo flujos de datos. Por ejemplo:En estos días, normalmente prefiero usar un contenedor que me permita usar,
foreach (string line in ...)
pero veo lo anterior como un patrón bastante idiomático. Por lo general, no es bueno tener efectos secundarios dentro de una afección, pero las alternativas generalmente implican la duplicación de código, y cuando conoce este patrón, es fácil acertar.fuente
EVIL EVIL EVIL
, pero no soy positivo.AsEither(...)
, creo que es un poco más claro queAsIf(...)
, así que puedo escribirmyAnimal.AsEither(dog => dog.Woof(), cat => cat.Meeow(), unicorn => unicorn.ShitRainbows())
.Si
as
falla, vuelvenull
.fuente
if
declaración y no en el alcance externo.if
puede tener un resultado bool y una asignación.Dog dog; if ((dog = animal as Dog) != null) { // Use Dog }
pero eso todavía introduce la variable en el alcance externo.Usted puede asignar el valor de la variable, siempre y cuando ya existe la variable. También puede definir el alcance de la variable para permitir que el nombre de la variable se use nuevamente más adelante en el mismo método, si eso es un problema.
asumiendo
obtiene salida:
El patrón de asignación de variables en la prueba también se usa al leer bloques de bytes de las secuencias, por ejemplo:
Sin embargo, el patrón de alcance variable utilizado anteriormente no es un patrón de código particularmente común y si lo viera utilizado en todas partes estaría buscando una forma de refactorizarlo.
fuente
Probablemente habrá en C # 6.0. Esta característica se llama "expresiones de declaración". Ver
https://roslyn.codeplex.com/discussions/565640
para detalles.
La sintaxis propuesta es:
De manera más general, la característica propuesta es que una declaración de variable local puede usarse como una expresión . Esta
if
sintaxis es solo una buena consecuencia de la característica más general.fuente
Try*
(por ejemplo,TryParse
). Esta característica no solo convierte dichas llamadas en una sola expresión (como deberían ser, IMO), sino que también permite una definición más clara de dichas variables. Me entusiasma que elout
parámetro de unTry
método tenga un alcance condicional; Esto hace que sea más difícil introducir ciertos tipos de errores.Uno de los métodos de extensión que me encuentro escribiendo y usando a menudo * es
Que podría usarse en esta situación como
Y luego
name
es el nombre del perro (si es un perro), de lo contrario es nulo.* No tengo idea si esto es efectivo. Nunca ha surgido como un cuello de botella en la elaboración de perfiles.
fuente
Ir contra la corriente aquí, pero tal vez lo estás haciendo mal en primer lugar. Verificar el tipo de un objeto casi siempre es un olor a código. ¿No tienen todos los animales, en su ejemplo, un nombre? Luego simplemente llame a Animal.name, sin verificar si es un perro o no.
Alternativamente, invierta el método de modo que llame a un método en Animal que haga algo diferente dependiendo del tipo concreto del Animal. Ver también: polimorfismo.
fuente
Declaración más corta
fuente
Aquí hay un código sucio adicional (aunque no tan sucio como el de Jon :-)) que depende de la modificación de la clase base. Creo que captura la intención mientras tal vez se pierde el punto:
fuente
Si tiene que hacer múltiples, como-si, uno tras otro (y usar polimorfismo no es una opción), considere usar una construcción SwitchOnType .
fuente
El problema (con la sintaxis) no está en la asignación, ya que el operador de asignación en C # es una expresión válida. Más bien, es con la declaración deseada, ya que las declaraciones son declaraciones.
Si debo escribir un código como ese, a veces (dependiendo del contexto más amplio) escribiré el código de esta manera:
Hay ventajas con la sintaxis anterior (que está cerca de la sintaxis solicitada) porque:
dog
fuera elif
dará lugar a un error de compilación, ya que no se le asigna un valor en otro lugar. (Es decir, no asignar endog
otro lugar).if/else if/...
(solo hay tantosas
como sea necesario para seleccionar una rama apropiada; este es el gran caso en el que lo escribo en este formulario cuando debo hacerlo).is/as
. (Pero también hecho conDog dog = ...
forma).Para aislarse verdaderamente
dog
del resto del mundo, se puede usar un nuevo bloque:Feliz codificación
fuente
puedes usar algo así
// Declarar variable bool temp = false;
fuente
Otra solución MALA con métodos de extensión :)
Personalmente prefiero la forma limpia:
fuente
Una declaración if no lo permitirá, pero un bucle for sí.
p.ej
En caso de que la forma en que funciona no sea obvia de inmediato, aquí hay una explicación paso a paso del proceso:
iteración.
fuente
fuente
IDK si esto ayuda a alguien pero siempre puede intentar usar un TryParse para asignar su variable. Aquí hay un ejemplo:
La variable total se declararía antes de su declaración if.
fuente
Acabo de insertar la instrucción if para crear una línea de código que se parezca a lo que le interesa. Simplemente ayuda a comprimir el código y descubrí que es más legible, especialmente cuando se anidan asignaciones:
fuente
Sé que llego súper tonto tarde a la fiesta, pero pensé que publicaría mi propia solución a este dilema ya que aún no lo he visto aquí (ni en ningún otro lado).
Con esto, puedes hacer cosas como:
NOTA IMPORTANTE: Si desea usar TryAs () usando una interfaz, DEBE tener esa interfaz heredando IAble.
¡Disfrutar! 🙂
fuente