2008-09-18 21 views
21

¿Cómo puedo hacer esto?Cambiar Tipo de Propiedad

switch(property.PropertyType){ 
    case typeof(Boolean): 
     //doStuff 
     break; 
    case typeof(String): 
     //doOtherStuff 
     break; 
    default: break; 
} 

que no quieren usar el nombre ya que la comparación de cadena para este tipo es simplemente terrible y puede estar sujeto a cambios.

Respuesta

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

puede utilizar un enfoque híbrido para TypeCode.Object donde dinámico 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.

+3

No funcionará si quiere comparar algo que no sea el tipo simple integrado porque TypeCode es una enumeración que no contiene nada excepto tipos simples como bool, int32, etc. ... –

+0

Por supuesto que es cierto. Pero estar fuera del alcance del ejemplo que omití en primer lugar. Agregado más tarde para aclarar ese punto. Gracias. –

+0

Bueno, en mi caso particular, solo serán tipos básicos. –

0

No se preocupe por el uso de cadenas dentro de un interruptor, porque si usted tiene varios el compilador lo convertirá automáticamente en una búsqueda de hash que proporciona un rendimiento decente a pesar de que parece bastante horrible.

El problema de las cuerdas de tipo cambiantes pueden ser solucionados por lo que es en un hash de las operaciones de búsqueda explícita a sí mismo y llenar los constents 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.

1

No puede hacer esto con el interruptor en C# ya que la caja tiene que ser constante.

Qué hay de malo en:

if(property.PropertyType == typeof(bool)) { 
    //dostuff; 
} 
else if (property.PropertyType == typeof(string)) { 
    //do other stuff; 
} 
+0

OP debe saber ya. Sin embargo +1 para contrarrestar downvote; también una solución válida, a veces es imposible reemplazar el poder de construcciones integradas. – nawfal

0

sólo tiene que utilizar la normal si/else if/else patrón:

if (property.PropertyType == typeof(Boolean)) 
{ 
} 
else if (property.PropertyType == typeof(String)) 
{ 
} 
else if (...) 
{ 
} 
3

No puede. Lo que puede hacer es crear una correlación entre tipos y un delegado utilizando 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"); 
0

recientemente que tenía que hacer algo similar y con el interruptor no era una opción. Hacer una == en el typeof (x) está bien, pero una forma más elegante podría ser la de 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 se puede utilizar el "es" palabra clave en de esta manera, creo que sólo funciona para objetos ...

2

creo que lo que está 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](); 
} 
1

yo personalmente prefiero el Dictionary<Type, other> acercan más ... Incluso puedo dar otro ejemplo: http://www.timvw.be/presenting-namevaluecollectionhelper/

En caso de que se empeñan en escribir un switch de los casos declaración se puede utilizar el nombre de Tipo ...

switch (blah.PropertyType.FullName) 
{ 
    case typeof(int).FullName: break; 
    case typeof(string).FullName: break; 
} 
+0

-1, el caso requiere * expresión constante. * – nawfal

+0

@nawfal He votado esto porque usted estan equivocados. Funciona con System.String. System.String es un tipo inmutable. – toATwork

+1

@toATwork Inmutable o no, 'case' requiere una expresión constante. Por ej. si System.String en su ejemplo se ve como 'case 'myCompileTimeValue": 'esto funcionará. Pero si parece 'case myRunTime.Value:' no se compilará. Las cosas podrían cambiar en futuras versiones de C# (posiblemente 7) con la coincidencia de patrones y todo. – nawfal

0

Sobre el stringmatching: era uno de los reqs en la cuestión de no hacerlo º stringmatching áspero.

El diccionario es un enfoque voy a utilizar cuando pongo 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, voy a volver a la nube de si/vigilara: S

Antes de PPL me pregunta qué quiero mi propia serialización: 1) .net xml serialización no serializa propiedades sin fijadores 2) la serialización debe cumplir con algunas reglas heredadas

+0

Puede omitir la limitación de propiedades agregando un conjunto vacío. cadena pública MyProp {get {return foo;} set {;}} –

1

C# 7.0 admitirá los tipos de conexión como parte de la función de coincidencia de patrones más grande. Este ejemplo está tomado de .NET blog post 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)); 
} 
Cuestiones relacionadas