using System;
static class Utility<T, TReturn>
{
public static TReturn Change(T arg)
{
// is there any solution to do this type casting but without dynamic keyword?
return (TReturn)(arg as dynamic);
}
}
class Program
{
static void Main(string[] args)
{
int i = 100;
try
{
short s = Utility<int,short>.Change(i);
Console.WriteLine(s);
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
}
}
回答
绝对如此。在这里,你去...
static class Utility<T, TReturn> {
public static TReturn Change(T arg) {
return (TReturn)Convert.ChangeType(arg, typeof(TReturn));
}
}
static class Utility<T, TReturn>
where T : TReturn
{
public static TReturn Change(T arg)
{
return (TReturn) arg;
}
}
您的代码不适用于提问者提供的代码。 'int'不是'short'。提问者正在寻找一种类型转换,而不仅仅是一个简单的转换。 – mattmc3 2010-10-12 04:05:32
您可以添加约束T : TReturn
。但是这不适用于您的值类型:
using System;
static class Utility<T, TReturn>
where T : TReturn
{
public static TReturn Change(T arg)
{
return (TReturn)(arg);
}
}
class Program
{
static void Main(string[] args)
{
string i = "100";
try
{
object s = Utility<string, object>.Change(i);
Console.WriteLine(s);
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
}
}
即使简单:
static class Utility<T, TReturn>
{
static TReturn Change(T arg, Converter<TReturn, T> convert)
{
System.Diagnostics.Debug.Assert(arg != null);
return convert(arg);
}
}
或者试试下面的,如果你不能接受一个自定义转换器的委托:
static class Utility<T, TReturn>
{
static TReturn Change(T arg)
{
return (TReturn) System.ComponentModel.TypeDescriptor.GetConverter(typeof(T)).ConvertTo(arg, typeof(TReturn));
}
}
使用Convert.ChangeType(object,Type)
的解决方案是不与使用动态调度的方法一样灵活。主要是因为很少有类型实现IConvertible。例如,假设你想从一个值类型转换为它的可空值类型,这会抛出一个异常。 下面是一个例子::
Converter<short, short?> test1 = @short =>(short?)Convert.ChangeType(@short, typeof(short?));
test1(5);
这是不通用的代码,但它仍然证明了它会炸掉点。更糟糕的是,在这种情况下,简单的演员实际上工作。你真正需要的是一个“智能”转换器。
首先,我们需要定义您愿意接受的惩罚。 如果您准备好调用DLR,这可能是您最安全的选择。该代码几乎保证做正确的事情。由于呼叫站点被缓存,如果调用足够的话,它实际上会表现得非常好。
我不会假装没有简单的解决方案。你最好的选择是开始考虑限制功能的范围或范围。例如,如果您将TResult的限制添加为IConvertible,那么您不必担心可空。尽管如此,它仍然会炸毁Enums。
你可以做的是建立一个转换器委托来处理返回类型的工作。然后按返回类型缓存它。您将始终禁用值类型,但其内存密集程度要低很多,因此必须缓存该方法调用的每个配对的委托。该逻辑基本上必须处理几种情况::
If(TReturn.IsValueType)
{
If(TReturn.IsEnum) Cast to Enum base type using Convert.To(base), then to Enum.
If(TReturn.IsNullable<>) Cast to Nullable<> generic type using Convert.To(base), then to Nullable<T>
If(TReturn.ISNullableEnum) Cast to Enum base type using Convert.To(base), then to Nullable enum.
Otherwise, just call Convert.To(TReturn) if that method exists.
}
If it's Iconvertible try calling Convert.ChangeType(object,Type) and cast as TReturn.
If no method has been found yet, try doing an explicit cast TReturn.
这对实现转换运算符的代码仍然失败,这不是IConvertible。但它非常接近你想要的。要添加对转换运算符的支持,您必须为每个TInput,TReturn缓存不同的委托。这是一个更大的混乱,因为你现在开始担心在某些情况下试图不加框,在那里它更容易调用拳击方法,并且需要很多工作才能得到正确的结果。除非这是必须成为代码库的一部分,否则我会避免使用这种清理工具,return (TReturn)(value as dynamic)
。
我为我的数据库层做了这样的事情,我目前正在尝试用更简单和不那么痛苦的动态代码替换.NET 3.5代码。 上述可能会比DLR代码略微(并且略微)执行得更好,并且不会像DLR呼叫那样安全或稳健。
谢谢。很好的解释。 – xport 2010-10-12 05:50:10
- 1. 动态设置泛型类型参数
- 2. 基于泛型参数的java泛型类型推断
- 3. 与类型的动态计数泛型类型参数
- 4. 我们可以使用工会进行类型转换吗?
- 5. 使用泛型类型参数类
- 6. 我们可以推断泛型输出类型吗?
- 7. 泛型类型参数和类型
- 8. 泛型类型参数不是类型?
- 9. 使用泛型类型的参数化构造函数基类
- 10. Java泛型类型参数
- 11. C#类型转换为泛型参数
- 12. 使用泛型将类型对象类型转换为泛型类型
- 13. 泛型类型作为泛型类型参数
- 14. 带泛型类型参数的网络泛型类型
- 15. 泛型 - 使用GetRuntimeMethod与类型参数
- 16. 我们如何使用Java中的泛型类型和基本类型工作
- 17. 泛型:基于通用类
- 18. 如何使用泛型类型参数调用泛型方法
- 19. 来自子类的C#泛型类型参数,可能吗?
- 20. 我可以从泛型类继承而不指定类型吗?
- 21. Java泛型 - 原始类型和参数化类型转换
- 22. 如何使用泛型类型的泛型列表泛型类
- 23. 将扩展方法应用于泛型类型泛型类型
- 24. 泛型类没有泛型函数中的类型参数
- 25. 多用于泛型类型
- 26. 使用自由绑定泛型类型作为类型参数
- 27. 在C#中使用类型参数的泛型类型
- 28. 泛型函数,类和“where”关键字
- 29. 从泛型基类型发射非泛型类型
- 30. 我们可以使用MemberFunction类型作为模板参数吗?
除了演员之外,你还想达到什么目的?你是否想避免为上面的例子写'(short)i'? – shahkalpesh 2010-10-12 03:59:18
这只是一个简单的例子。 – xport 2010-10-12 04:03:12