12

假设我们有一个带有单个泛型方法的接口:

public interface IExtender
{
    T GetValue<T>(string tag);
}

以及它的一个简单实现 A,它根据“tag”参数返回两种不同类型(B 和 C)的实例:

public class A : IExtender
{
    public T GetValue<T>(string tag)
    {
        if (typeof(T) == typeof(B) && tag == null)
            return (T)(object) new B();
        if (typeof(T) == typeof(C) && tag == "foo")
            return (T)(object) new C();
        return default(T);
    }
}

是否有可能避免双重演员(T)(object)?或者,有没有办法告诉编译器“嘿,我确信这个转换在运行时不会失败,让我在不先转换为对象的情况下完成它!”

4

6 回答 6

9

或者,有没有办法告诉编译器“嘿,我确信这个转换在运行时不会失败,让我在不先转换为对象的情况下完成它!”

不,该语言是故意设计来防止这种情况的。Eric Lippert最近在博客中谈到了这一点。我同意这很烦人,但它确实有某种意义。

老实说,像这样的“通用”方法通常有点设计味道。如果一个方法必须有各种不同类型的特殊情况,您至少应该考虑使用单独的方法。( GetB, GetC)

于 2012-07-19T07:21:50.770 回答
6
public T MyMethod<T>(string tag) where T : class
    {
        return new A() as T;
    }
于 2012-07-19T07:28:29.650 回答
3

检查这个样本:

    public T GetValue<T>(string tag) where T : class, new()
    {
        if (typeof(T) == typeof(B) && tag == null)
            return new T();
        if (typeof(T) == typeof(C) && tag == "foo")
            return new T();
        return default(T);
    }

不需要强制转换,您可以创建“T”的实例,只需添加说 T 是一个类并且它具有无参数构造函数的通用约束,因此您不需要创建另一个基类型,并且您可以确保只有合适的类型将通过这个通用方法。

于 2012-07-19T07:26:47.483 回答
1

您可以使用动态来存储您的真实结果,但您必须确保泛型参数类型是您返回的正确类型。

TResult GetResult<TResult>() 
{
    dynamic r = 10;
    return r;
}
于 2018-10-17T20:51:47.443 回答
0

不,那是不可能的。这样做的唯一方法是让编译器知道关于T. 正如泛型参数约束列表所证明的那样,在 C# 中没有定义任何约束来要求特定转换的可用性。

于 2012-07-19T07:22:49.733 回答
0

如果你让 B 和 C 实现相同的接口,你可以在你的T. 可能不完全是您想要的,但正如其他人所建议的那样,您想要的实际上是不可能的。

public interface IclassBndC {}

public class B : IclassBandC {}

public class C : IclassBandC {}

public class A : IExtender
{
    public T GetValue<T>(string tag) where T : IclassBandC 
    {
        if (tag == null)
            return new B();
        if (tag == "foo")
            return new C();
        return default(T);
    }
}
于 2012-07-19T07:24:15.273 回答