c# - quedar - Usando Case/Switch y GetType para determinar el objeto
switch typeof c# (11)
Dependiendo de lo que esté haciendo en la instrucción switch, la respuesta correcta es polimorfismo. Simplemente ponga una función virtual en la clase interfaz / base y anule para cada tipo de nodo.
Posible duplicado:
C # - ¿Hay una mejor alternativa que esta para ''encender el tipo''?
Si desea switch
un tipo de objeto, ¿cuál es la mejor manera de hacerlo?
Fragmento de código
private int GetNodeType(NodeDTO node)
{
switch (node.GetType())
{
case typeof(CasusNodeDTO):
return 1;
case typeof(BucketNodeDTO):
return 3;
case typeof(BranchNodeDTO):
return 0;
case typeof(LeafNodeDTO):
return 2;
default:
return -1;
}
}
Sé que esto no funciona de esa manera, pero me preguntaba cómo podrías resolver esto. ¿Es adecuada una declaración if/else
en este caso?
¿O usa el interruptor y agrega .ToString()
al tipo?
En la publicación de blog de MSDN, blogs.msdn.com/peterhal/archive/2005/07/05/435760.aspx es información sobre por qué .NET no proporciona el cambio de tipos.
Como de costumbre, las soluciones siempre existen.
Este no es el mío, pero lamentablemente he perdido la fuente. Hace posible el cambio de tipos, pero personalmente creo que es bastante incómodo (la idea del diccionario es mejor):
public class Switch
{
public Switch(Object o)
{
Object = o;
}
public Object Object { get; private set; }
}
/// <summary>
/// Extensions, because otherwise casing fails on Switch==null
/// </summary>
public static class SwitchExtensions
{
public static Switch Case<T>(this Switch s, Action<T> a)
where T : class
{
return Case(s, o => true, a, false);
}
public static Switch Case<T>(this Switch s, Action<T> a,
bool fallThrough) where T : class
{
return Case(s, o => true, a, fallThrough);
}
public static Switch Case<T>(this Switch s,
Func<T, bool> c, Action<T> a) where T : class
{
return Case(s, c, a, false);
}
public static Switch Case<T>(this Switch s,
Func<T, bool> c, Action<T> a, bool fallThrough) where T : class
{
if (s == null)
{
return null;
}
T t = s.Object as T;
if (t != null)
{
if (c(t))
{
a(t);
return fallThrough ? s : null;
}
}
return s;
}
}
Uso:
new Switch(foo)
.Case<Fizz>
(action => { doingSomething = FirstMethodCall(); })
.Case<Buzz>
(action => { return false; })
En realidad, prefiero el enfoque dado como la respuesta aquí: ¿hay una alternativa mejor que esta para ''cambiar el tipo''?
Sin embargo, existe un buen argumento acerca de no implementar ningún tipo de methids de comparación en un lenguaje orientado a objetos como C #. Como alternativa, podría extender y agregar funcionalidad requerida adicional usando herencia.
Este punto fue discutido en los comentarios del blog de los autores aquí: http://blogs.msdn.com/b/jaredpar/archive/2008/05/16/switching-on-types.aspx#8553535
Encontré este punto extremadamente interesante que cambió mi enfoque en una situación similar y solo espero que esto ayude a otros.
Saludos cordiales, Wayne
Esto no resolverá directamente su problema ya que desea activar sus propios tipos definidos por el usuario, pero para el beneficio de otros que solo desean activar los tipos integrados, puede usar la enumeración de TypeCode :
switch (Type.GetTypeCode(node.GetType()))
{
case TypeCode.Decimal:
// Handle Decimal
break;
case TypeCode.Int32:
// Handle Int32
break;
...
}
Me enfrento con el mismo problema y encontré esta publicación. ¿Esto es lo que significa el enfoque IDictionary?
Dictionary<Type, int> typeDict = new Dictionary<Type, int>
{
{typeof(int),0},
{typeof(string),1},
{typeof(MyClass),2}
};
void Foo(object o)
{
switch (typeDict[o.GetType()])
{
case 0:
Print("I''m a number.");
break;
case 1:
Print("I''m a text.");
break;
case 2:
Print("I''m classy.");
break;
default:
break;
}
}
Si es así, no puedo decir que soy partidario de reconciliar los números en el diccionario con las declaraciones de casos.
Esto sería ideal, pero la referencia del diccionario lo mata:
void FantasyFoo(object o)
{
switch (typeDict[o.GetType()])
{
case typeDict[typeof(int)]:
Print("I''m a number.");
break;
case typeDict[typeof(string)]:
Print("I''m a text.");
break;
case typeDict[typeof(MyClass)]:
Print("I''m classy.");
break;
default:
break;
}
}
¿Hay alguna otra implementación que haya pasado por alto?
Puedes hacerlo:
function void PrintType(Type t) {
var t = true;
new Dictionary<Type, Action>{
{typeof(bool), () => Console.WriteLine("bool")},
{typeof(int), () => Console.WriteLine("int")}
}[t.GetType()]();
}
Está claro y es fácil. Es un poco más lento que almacenar en caché el diccionario en alguna parte ... pero para muchos códigos esto no importará de todos modos ...
Puedes hacerlo:
if (node is CasusNodeDTO)
{
...
}
else if (node is BucketNodeDTO)
{
...
}
...
Mientras que eso sería más elegante, posiblemente no sea tan eficiente como algunas de las otras respuestas aquí.
Si realmente tuviera que switch
el tipo de objeto, usaría .ToString()
. Sin embargo, lo evitaría a toda costa: IDictionary<Type, int>
mucho mejor, el visitor podría ser un exagerado pero, de lo contrario, sigue siendo una solución perfecta.
Solo usaría una declaración if. En este caso:
Type nodeType = node.GetType();
if (nodeType == typeof(CasusNodeDTO))
{
}
else ...
La otra forma de hacer esto es:
if (node is CasusNodeDTO)
{
}
else ...
El primer ejemplo es verdadero solo para tipos exactos, donde este último también verifica la herencia.
Un enfoque es agregar un método virtual GetNodeType () puro a NodeDTO y anularlo en los descendientes para que cada descendiente devuelva el tipo real.
Usaría la cadena (Nombre) en la parte superior del interruptor:
private int GetNodeType(NodeDTO node)
{
switch (node.GetType().Name)
{
case "CasusNodeDTO":
return 1;
break;
case "BucketNodeDTO":
return 3;
break;
// ...
default:
return -1;
break;
}
}