将泛型类型参数转换为C#中的特定类型

时间:2016-08-31 08:27:06

标签: c# .net generics

如果您需要将泛型类型参数强制转换为特定类型,我们可以将其转换为对象并执行如下所示的转换,

void SomeMethod(T t)
{
    SomeClass obj2 = (SomeClass)(object)t;
}

是否有更好的方法来实现这一目标,而不是将其转换为对象,然后再转换为特定类型。

问题

我有一个泛型函数接受泛型类型参数,在函数内部基于类型检查我做了一些操作,如下面

    void SomeMethod(T t)
    {
        if (typeof(T).Equals(typeof(TypeA)))
        {
            TypeA = (TypeA)(object)t;
            //Do some operation
        }
        else if (typeof(T).Equals(typeof(TypeB)))
        {
            TypeB = (TypeB)(object)t;
            //Do some operation
        }
    }

7 个答案:

答案 0 :(得分:5)

更好的设计是对它进行约束,这种约束在类型T和您希望在方法中期望的类之间是常见的,在本例中为SomeClass

class SomeConsumer<T> where T : ISomeClass
{
    void SomeMethod(T t)
    {
        ISomeClass obj2 = (ISomeClass) t;
    }
}

interface ISomeClass{}

class SomeClass : ISomeClass {}

根据问题编辑

进行编辑

这是糟糕的设计。尝试将“操作”移动到类本身中,以便调用者不必知道类型。如果不可能分享更多正在做的事情,那么你想要完成的是你没有一堆if / else语句,其中执行取决于传递给方法的对象类型。

class SomeConsumer<T> where T : ISomeClass
{
    void SomeMethod(T t)
    {
        ISomeClass obj2 = (ISomeClass) t;
        // execute
        t.Operation();
    }
}

interface ISomeClass{
    void Operation();
}

class SomeClass : ISomeClass {
    public void Operation(){/*execute operation*/}
}

答案 1 :(得分:5)

您可以使用Convert.ChangeType

SomeClass obj2 = (SomeClass)Convert.ChangeType(t, typeof(SomeClass));

尽管如此,请记住,如果演员表无效,这将引发异常。

答案 2 :(得分:3)

使用as

SomeClass obj2 = t as SomeClass;

这不会抛出异常,如果转换失败,t将为null。

我真的不知道你要做什么,但我希望你不要错过Generics的观点。

如果您打算将方法限制为键入SomeClass和后代:

void SomeMethod(T t)  where T : SomeClass

答案 3 :(得分:1)

您可以as使用该案例

void SomeMethod(T t)
{
    SomeClass obj2 = t as SomeClass;
}

答案 4 :(得分:1)

如果输入类型T与目标类型TypeATypeB(使用参数约束)之间没有关系,我们正在纯粹关注铸造问题,答案很简单:

不,没有比你正在使用的方法更好的方法!!!

我同意其他人的意见,如果你在这个对象上做更多的操作,你可能想选择不同的设计。

答案 5 :(得分:1)

偶然发现此问题,并想为后来发现此问题的任何人提供最新答案。在较新的C#版本(我撰写本文时为8.0)中,pattern matching将允许您以更加简洁的方式执行此操作:

void SomeMethod<T>(T t)
{
    switch(t)
    {
        case TypeA a:
            // Do some operation using a.
            Console.WriteLine($"{a} is a TypeA!");
            break;
        case TypeB b:
            // Do some operation using b.
            Console.WriteLine($"{b} is a TypeB!");
            break;
        default:
            // Handle this case.
            Console.WriteLine("I don't know what this type is.");
            break;
    }
}

这将检查对象的类型,如果找到匹配项,则将其一步分配给指定的变量,然后在该情况下可以使用该变量。 (您也可以在if语句中执行类似的操作:if (t is TypeA a) a.DoSomething(); ...

话虽如此,我也同意其他答复,即您应该尽可能地限制这一点(void SomeMethod<T>(T t) where T : ISomeInterface {...}),或者在可能的情况下将操作移至要测试的类中。

答案 6 :(得分:0)

我知道这是一个迟到的问题,但在这里你可以做什么

一个很好的选择是使你的函数接受类object的参数,并根据需要做你的开关案例

只需进行投射

YourClass = (YourClass) parameterObject;