c# - multiple - Cambiar sobre PropertyType
switch case c++ (10)
C # 7.0 admitirá el encendido de tipos como parte de una función de coincidencia de patrones más grande. Este ejemplo se toma de la publicación de blog .NET que anuncia nuevas características:
switch(shape)
{
case Circle c:
WriteLine($"circle with radius {c.Radius}");
break;
case Rectangle s when (s.Length == s.Height):
WriteLine($"{s.Length} x {s.Height} square");
break;
case Rectangle r:
WriteLine($"{r.Length} x {r.Height} rectangle");
break;
default:
WriteLine("<unknown shape>");
break;
case null:
throw new ArgumentNullException(nameof(shape));
}
¿Cómo puedo hacer que esto funcione?
switch(property.PropertyType){
case typeof(Boolean):
//doStuff
break;
case typeof(String):
//doOtherStuff
break;
default: break;
}
No quiero usar el nombre ya que la comparación de cadenas para tipos es horrible y puede estar sujeta a cambios.
Creo que lo que estás buscando aquí es un buen Mapa. Usando delegados y un IDictionary genérico puedes hacer lo que quieras.
Pruebe algo como esto:
private delegate object MyDelegate();
private IDictionary<Type, MyDelegate> functionMap = new IDictionary<Type, MyDelegate>();
public Init()
{
functionMap.Add(typeof(String), someFunction);
functionMap.Add(tyepof(Boolean), someOtherFunction);
}
public T doStuff<T>(Type someType)
{
return (T)functionMap[someType]();
}
No puede hacer esto con el interruptor en c # ya que el caso tiene que ser constante.
Lo que está mal con:
if(property.PropertyType == typeof(bool)) {
//dostuff;
}
else if (property.PropertyType == typeof(string)) {
//do other stuff;
}
No puedes. Lo que puede hacer es crear un mapeo entre Types y un delegado usando un diccionario:
var TypeMapping = new Dictionary<Type, Action<string>>(){
{typeof(string), (x)=>Console.WriteLine("string")},
{typeof(bool), (x)=>Console.WriteLine("bool")}
};
string s = "my string";
TypeMapping[s.GetType()]("foo");
TypeMapping[true.GetType()]("true");
No se preocupe por usar cadenas dentro de un conmutador, porque si tiene varias, el compilador las convertirá automáticamente en una búsqueda hash, lo que le dará un rendimiento decente a pesar de parecer bastante desagradable.
El problema del cambio de cadenas de tipo puede resolverse convirtiéndolo en una búsqueda explícita de hash usted mismo y rellenando las constelaciones del hash en un constructor estático. De esta forma, el hash se rellena con las cadenas correctas en tiempo de ejecución para que permanezcan correctas.
Personalmente, prefiero el enfoque del Dictionary<Type, other>
más ... Incluso puedo ofrecerle otro ejemplo: http://www.timvw.be/presenting-namevaluecollectionhelper/
En caso de que insista en escribir una declaración de cambio de mayúscula, podría usar el nombre de Tipo ...
switch (blah.PropertyType.FullName)
{
case typeof(int).FullName: break;
case typeof(string).FullName: break;
}
Recientemente tuve que hacer algo similar y usar el interruptor no era una opción. Hacer un == en el tipo de (x) está bien, pero una manera más elegante podría ser hacer algo como esto:
if(property.PropertyType is bool){
//dostuff;
}
else if (property.PropertyType is string){
//do other stuff;
}
Pero no estoy seguro de que pueda usar la palabra clave "es" de esta manera, creo que solo funciona para objetos ...
Simplemente use el patrón normal if / else if / else:
if (property.PropertyType == typeof(Boolean))
{
}
else if (property.PropertyType == typeof(String))
{
}
else if (...)
{
}
Sobre el stringmatching: fue uno de los requisitos en la pregunta no hacerlo a través de stringmatching.
El diccionario es un enfoque que usaré cuando coloque todo este algoritmo de serialización en su propia biblioteca. Por ahora, primero probaré el typeCode ya que mi caso solo usa tipos básicos. Si eso no funciona, volveré al enjambre de if / elses: S
Antes la gente me pregunta por qué quiero mi propia serialización: 1) .net serialización xml no serializa propiedades sin setters 2) serialización tiene que cumplir con algunas reglas heredadas
System.Type propertyType = typeof(Boolean);
System.TypeCode typeCode = Type.GetTypeCode(propertyType);
switch (typeCode)
{
case TypeCode.Boolean:
//doStuff
break;
case TypeCode.String:
//doOtherStuff
break;
default: break;
}
Puedes usar un enfoque híbrido para TypeCode.Object donde dinámicas si con typeof. Esto es muy rápido porque para la primera parte, el interruptor, el compilador puede decidir basándose en una tabla de búsqueda.