是否可以将变量转换为存储在另一个变量中的类型?

时间:2022-09-11 19:47:38

This is what I need to do:

这就是我需要做的事情:

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

Can something like this be done?

可以这样做吗?

5 个解决方案

#1


No, you cannot. C# does not implement duck typing.

你不能。 C#没有实现duck typing。

You must implement an interface and cast to it.

您必须实现一个接口并强制转换它。

(However there are attempts to do it. Look at Duck Typing Project for an example.)

(但是有人试图这样做。看看鸭子打字项目的例子。)

#2


You can use the Convert.ChangeType method.

您可以使用Convert.ChangeType方法。

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

#3


Your original question was flawed in that you ask to treat a variable as a type which is not known at compile time but note that you have string defined on the left hand side when you declare your variable. C# as of 3.5 is statically typed.

您的原始问题存在缺陷,因为您要求将变量视为在编译时未知的类型,但请注意,在声明变量时,您在左侧定义了字符串。从3.5开始的C#是静态类型的。

Once dynamic is available you could do something like this:

一旦动态可用,您可以执行以下操作:

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

For when you don't know what the type is but you know it will always support the instance method FunctionThatExistsInBarType();

因为当你不知道什么是类型但是你知道它总是支持实例方法FunctionThatExistsInBarType();

for now you are forced to use reflection (or code gen which really amounts to much the same thing but more expensive up front and faster later).

现在你*使用反射(或代码生成实际上相同的东西,但前面更昂贵,后来更快)。

// 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);

#4


Since dynamics were added to c#, I think we can do it in this way:

由于动态被添加到c#中,我认为我们可以这样做:

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

#5


Provided you know all required types at compile-time, duck typingis (sort of) possible:

如果您在编译时知道所有必需类型,则可以使用duck typing(类型):

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)"; }
}

Output:

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

If you end up implementing a lot of methods that basically do exactly the same, consider implementing an interface.

如果最终实现了许多基本上完全相同的方法,请考虑实现一个接口。

#1


No, you cannot. C# does not implement duck typing.

你不能。 C#没有实现duck typing。

You must implement an interface and cast to it.

您必须实现一个接口并强制转换它。

(However there are attempts to do it. Look at Duck Typing Project for an example.)

(但是有人试图这样做。看看鸭子打字项目的例子。)

#2


You can use the Convert.ChangeType method.

您可以使用Convert.ChangeType方法。

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

#3


Your original question was flawed in that you ask to treat a variable as a type which is not known at compile time but note that you have string defined on the left hand side when you declare your variable. C# as of 3.5 is statically typed.

您的原始问题存在缺陷,因为您要求将变量视为在编译时未知的类型,但请注意,在声明变量时,您在左侧定义了字符串。从3.5开始的C#是静态类型的。

Once dynamic is available you could do something like this:

一旦动态可用,您可以执行以下操作:

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

For when you don't know what the type is but you know it will always support the instance method FunctionThatExistsInBarType();

因为当你不知道什么是类型但是你知道它总是支持实例方法FunctionThatExistsInBarType();

for now you are forced to use reflection (or code gen which really amounts to much the same thing but more expensive up front and faster later).

现在你*使用反射(或代码生成实际上相同的东西,但前面更昂贵,后来更快)。

// 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);

#4


Since dynamics were added to c#, I think we can do it in this way:

由于动态被添加到c#中,我认为我们可以这样做:

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

#5


Provided you know all required types at compile-time, duck typingis (sort of) possible:

如果您在编译时知道所有必需类型,则可以使用duck typing(类型):

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)"; }
}

Output:

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

If you end up implementing a lot of methods that basically do exactly the same, consider implementing an interface.

如果最终实现了许多基本上完全相同的方法,请考虑实现一个接口。