C# 将返回值强制转换为泛型类型
假设我们有一个带有单个泛型方法的接口:C# 将返回值强制转换为泛型类型,c#,generics,C#,Generics,假设我们有一个带有单个泛型方法的接口: public interface IExtender { T GetValue<T>(string tag); } 公共接口IExtender { T GetValue(字符串标记); } 以及它的一个简单实现a,它根据“tag”参数返回两种不同类型(B和C)的实例: public class A : IExtender { public T GetValue<T>(string tag) {
public interface IExtender
{
T GetValue<T>(string tag);
}
公共接口IExtender
{
T GetValue(字符串标记);
}
以及它的一个简单实现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);
}
}
公共A类:IExtender
{
公共T GetValue(字符串标记)
{
if(typeof(T)=typeof(B)&&tag==null)
返回(T)(对象)新的B();
if(typeof(T)=typeof(C)&&tag==“foo”)
返回(T)(对象)新C();
返回默认值(T);
}
}
是否可以避免双重强制转换(T)(对象)
?或者,有没有一种方法可以告诉编译器“嘿,我确信这个强制转换在运行时不会失败,让我在不首先强制转换到对象的情况下执行它!”
或者,有没有一种方法可以告诉编译器“嘿,我确信这个强制转换在运行时不会失败,让我在不首先强制转换到对象的情况下执行它!”
不,语言是故意设计来防止这种情况发生的。埃里克·利珀特。我同意这很烦人,但确实有一定的道理
老实说,像这样的“通用”方法通常有点设计味道。如果一个方法必须具有不同类型的特殊情况,那么至少应该考虑使用单独的方法。(
GetB
,GetC
)不,这是不可能的。唯一的方法是让编译器知道关于T
的附加假设。正如所证明的,C中没有定义任何约束来要求特定类型转换的可用性。如果让B和C实现相同的接口,您可以在T
上使用a。也许不完全是你想要的,但正如其他人所建议的那样,你想要的其实是不可能的
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);
}
}
公共接口IclassBndC{}
公共B类:IclassBandC{}
公共C类:IclassBandC{}
公开A类:IExtender
{
公共T GetValue(字符串标记),其中T:IclassBandC
{
if(标记==null)
返回新的B();
如果(标记==“foo”)
返回新的C();
返回默认值(T);
}
}
检查此示例:
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);
}
public T GetValue(字符串标记),其中T:class,new()
{
if(typeof(T)=typeof(B)&&tag==null)
返回新的T();
if(typeof(T)=typeof(C)&&tag==“foo”)
返回新的T();
返回默认值(T);
}
不需要强制转换,您可以创建“T”的实例,只需添加泛型约束,说明T是一个类,并且它具有无参数构造函数,这样您就不需要创建另一个基类型,并且您可以确保只有合适的类型将通过此泛型方法。public T MyMethod(字符串标记),其中T:class
public T MyMethod<T>(string tag) where T : class
{
return new A() as T;
}
{
将新的A()返回为T;
}
您可以使用dynamic来存储实际结果,但必须确保泛型参数类型是您返回的正确类型
TResult GetResult<TResult>()
{
dynamic r = 10;
return r;
}
TResult GetResult()
{
动态r=10;
返回r;
}
为什么需要(T)(对象)转换?你可以直接(T)新的C()对吗?@Anuraj:不,这就是问题的关键所在。请阅读我在回答中引用的博客文章。注意,这要求您可以修改B
和C
@O.R.Mapper true,我是否遗漏了一点不可能的内容?您没有,但没有提到B
和C
是由OP编写的,而不是预定义和密封的。我认为应该提到限制。好吧,这就是当你(我,真的)试图简化代码以作为示例发布时发生的情况。在实际的代码中,实例已经存在,我不能对t施加任何约束。所以,是的,这是可行的(谢谢!),但不能解决我的问题。是的。GetB、GetC和GetEtc在这里不是一个选项,但我不知道这是否是详细讨论设计的正确地方。无论如何,第一段和链接是我一直在寻找的答案。谢谢。是的,这是可能的,在不止一个方面,有时它是解决设计问题的唯一好方法。这就是为什么引入了动态关键字。还有Convert.ChangeType。@DinoDini:我认为这两个都没有真正做到OP所说的。OP不想执行任何实际值转换-他们只是想避免双重强制转换。有效地使用dynamic只会使到对象的转换隐式化,但它不会以任何有用的方式删除它。使用dynamic cast是可能的。实际答案是。在这一页的底部。同样,这并没有真正删除强制转换-它只是使其隐式而不是显式。它的表现也可能不如双重演员。这正是我想要的!