2009-01-21 14 views
17

Esto es lo que tengo que hacer:¿Es posible convertir una variable en un tipo almacenado en otra variable?

object foo = GetFoo(); 
Type t = typeof(BarType); 
(foo as t).FunctionThatExistsInBarType(); 

¿Puede algo como esto puede hacer?

+0

¿Cómo sabes que es una cadena que desea en el lado izquierdo de los iguales en la última línea de tu ejemplo? En otras palabras, ¿qué vas a hacer con la barra que significa que no puedes usar "object bar = (object) foo;" ? –

+0

No lo sé, la cadena fue solo un ejemplo. Edité el fragmento. –

Respuesta

13

No, no se puede. C# no implementa duck typing.

debe implementar una interfaz y fundido a ella.

(Sin embargo, hay intentos de hacerlo. Mira Duck Typing Project para un ejemplo.)

+0

Sí, puedes. Mire la respuesta de GvS :-) –

+1

Aún necesita implementar la interfaz (IConvertible en este caso), y saber de antemano cuál es el tipo de conversión. – Quassnoi

+0

he marcado esta respuesta como aceptada uno que no uso el consejo de Quassnoi e implementado un interfaz para echar a ella, pero de GVS y respuestas de shuggycouk son demasiado grandes. –

20

Usted puede utilizar el método Convert.ChangeType.

object foo = GetFoo(); 
Type t = typeof(string); 
string bar = (string)Convert.ChangeType(foo, t); 
+6

Esto es útil solo si el objeto implementa IConvertible – Quassnoi

+4

He usado cadena solo como un ejemplo. El problema es que no sé el tipo de destino, así que no puedo realizar esta barra xyz = (xyz) Convert.Change ... cast. –

+0

Convert.ChangeType no está emitiendo, está convirtiendo. es decir, crear un nuevo objeto del tipo especificado. Si quieres lanzar para decir ICollection esto no funcionará. – Hoots

4

Su pregunta original era defectuoso en el que le pida para tratar una variable como un tipo que no se conoce en tiempo de compilación, pero en cuenta que tiene cadena definida en el lado izquierdo cuando se declara la variable. C# a partir de 3.5 está tipado estáticamente.

Una vez dinámico está disponible se podría hacer algo como esto:

dynamic foo = GetFoo(); 
foo.FunctionThatExistsInBarType(); 

Para cuando usted no sabe lo que es el tipo pero sabes que siempre va a apoyar el método de instancia FunctionThatExistsInBarType();

por ahora se ven obligados a utilizar la reflexión (o código de generación que en realidad equivale a lo mismo, pero más caro y más rápido en la delantera más adelante).

// any of these can be determined at runtime 
Type t = typeof(Bar); 
string methodToCall = "FunctionThatExistsInBarType"; 
Type[] argumentTypes = new Type[0]; 
object[] arguments = new object[0]; 
object foo; 
// invoke the method - 
// example ignores overloading and exception handling for brevity 
// assumption: return type is void or you don't care about it 
t.GetMethod(methodToCall, BindingFalgs.Public | BindingFlags.Instance) 
    .Invoke(foo, arguments); 
+1

El tipo de cadena fue solo un ejemplo (no es bueno); Edité el fragmento de código, espero que esté más claro ahora. –

+0

Derecha - para esto (pre dinámico) debe usar reflexión. Voy a editar para tomar eso en cuenta – ShuggyCoUk

0

A condición de que conoce todos los tipos requeridos en tiempo de compilación, duck typing es (más o menos) posible:

class BarFoo {} 
class Foo {} 
class Bar {} 

class Program 
{ 
    static void Main() 
    { 
     var foo = new Foo(); 
     var bar = new Bar(); 
     var barfoo = new BarFoo(); 

     Console.WriteLine(DoStuff(foo)); 
     Console.WriteLine(DoStuff(bar)); 
     Console.WriteLine(DoStuff(barfoo)); 

    } 

    static string DoStuff(Foo foo) { return "DoStuff(Foo foo)"; } 
    static string DoStuff(Bar bar) { return "DoStuff(Bar bar)"; } 
    static string DoStuff(Base fb) { return "DoStuff(object fb)"; } 
} 

Salida:

Dostuff(Foo foo) 
Dostuff(Bar bar); 
DoStuff(object fb); 

Si al final de la implementación de una gran cantidad de métodos que básicamente hacen exactamente lo mismo, considere implementar una interfaz.

+0

Uh ... Cuatro años después ... Oh, bueno. –

+2

Esto no es tipa pato. Es polimorfismo (se aplica a la función 'DoStuff'). –

2

Dado que la dinámica se añadieron a C#, creo que podemos hacerlo de esta manera:

class Program { 
    static void Main(string[] args) { 
     List<int> c = new List<int>(); 
     double i = 10.0; 
     Type intType = typeof(int); 
     c.Add(CastHelper.Cast(i, intType)); // works, no exception! 
    } 
} 

class CastHelper { 
    public static dynamic Cast(object src, Type t) { 
     var castMethod = typeof(CastHelper).GetMethod("CastGeneric").MakeGenericMethod(t); 
     return castMethod.Invoke(null, new[] { src }); 
    } 
    public static T CastGeneric<T>(object src) { 
     return (T)Convert.ChangeType(src, typeof(T)); 
    } 
} 
+1

Esto funcionó como un encanto donde otras soluciones no lo hicieron. – BrotherOdin

+0

Perfecto, gracias! – Stark

Cuestiones relacionadas