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. 我可以@注入泛型类型吗?
- 3. 我们可以有一个泛型的类类型吗?
- 4. 动态设置泛型类型参数
- 5. 创建动态泛型类型参数
- 6. 基于泛型参数的java泛型类型推断
- 7. 基于泛型参数类型的类型推断(德尔福)
- 8. 当前类的类型可以用作泛型类型参数的值吗?
- 9. 我们可以使用返回类型与输入参数类型相同的泛型函数吗?
- 10. 我们可以使用工会进行类型转换吗?
- 11. 与类型的动态计数泛型类型参数
- 12. 使用泛型类型参数类
- 13. 我可以使用反射类型作为类型参数吗?
- 14. 传递类型参数动态地泛型类型
- 15. 我们可以推断泛型输出类型吗?
- 16. 泛型类型参数不是类型?
- 17. 泛型类型参数和类型
- 18. 我们可以在C#中的泛型中写List作为类型参数吗?
- 19. 使用泛型类型的参数化构造函数基类
- 20. 从基类型的行动泛型
- 21. Java泛型类型参数
- 22. 泛型类型参数
- 23. C#类型转换为泛型参数
- 24. 使用泛型将类型对象类型转换为泛型类型
- 25. 泛型类型作为泛型类型参数
- 26. 带泛型类型参数的网络泛型类型
- 27. C#将泛型类型作为泛型类型参数传递?
- 28. (开放泛型类型)泛型类型,没有指定参数
- 29. 泛型 - 使用GetRuntimeMethod与类型参数
- 30. 我们如何使用Java中的泛型类型和基本类型工作
除了演员之外,你还想达到什么目的?你是否想避免为上面的例子写'(short)i'? – shahkalpesh 2010-10-12 03:59:18
这只是一个简单的例子。 – xport 2010-10-12 04:03:12