泛型:铸造和值类型,这是为什么违法? [英] Generics: casting and value types, why is this illegal?

查看:157
本文介绍了泛型:铸造和值类型,这是为什么违法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

为什么这是一个编译时错误?

 公共TCastTo CastMe< TSource,TCastTo>(TSource我)
{
     返回(TCastTo)我;
}
 

错误:

  

ANNOT转换类型'TSource'到'TCastTo

为什么是这样的一个运行时错误?

 公共TCastTo CastMe< TSource,TCastTo>(TSource我)
{
     返程(TCastTo)(对象)我;
}

INT一个= 4;
长B = CastMe<的int,long>(一); // InvalidCastException的

//这个人为的例子工程
INT AA = 4;
INT BB = CastMe< INT,INT>(AA);

//这也适用,问题是有限的值类型
字符串s =富;
对象o = CastMe<字符串,对象>(S);
 

我已经搜查SO和互联网的答案,这一点,并发现了许多类似的通用相关的铸造问题的解释,但我不能找到这个特殊的简单情况下任何东西。

解决方案
  

为什么这是一个编译时错误?

的问题是,值类型的每个可能的组合具有的不同的规则是什么的铸造装置。铸造一个64位的双为16位int是从铸造一个十进制为float,等完全不同的code。的可能性的数量是巨大的。因此,认为像编译器。 什么code是应该生成你的程序的编译器?

编译器必须产生code,它的重新开始编译器在运行时,请问类型的新的分析,并动态地发出合适的code 的。

这看起来可能是更多的工作,比你少有望获得与仿制药的性能,所以我们干脆取缔它。如果你真正想要的是让编译器再次启动并执行类型的分析,在C#4使用动态;这就是它做什么。

  

为什么是这样的一个运行时错误?

同样的道理。

一个装箱的int可能只拆箱为int(或INT),用于与上述相同的理由;如果CLR试图做一切可能的转换,从一个装箱值类型为所有其他可能的值类型,那么本质上,它具有的在运行时再次运行编译器的。这将是异常缓慢。

  

那么,为什么它不是一个错误的引用类型?

由于每一个引用类型转换是相同的所有其他引用类型转换:你询问的对象,以确定它是来自于或等同于所需的类型。如果不是的话,你/假(如果使用了AS /是经营者)抛出一个异常(如果做一个演员),或导致空。该规则是在某种程度上,它们不是值类型引用类型是一致的。记住的引用类型的知道自己的类型的。值类型没有;值类型,变量做存储的是,知道适用于那些位的类型语义的唯一的事。值类型的包含它们的值并没有额外的信息的。引用类型包含的值加上许多额外的数据。

有关详细信息,请参阅我关于这个问题的文章:

<一个href="http://ericlippert.com/2009/03/03/re$p$psentation-and-identity/">http://ericlippert.com/2009/03/03/re$p$psentation-and-identity/

Why is this a compile time error?

public TCastTo CastMe<TSource, TCastTo>(TSource i)
{
     return (TCastTo)i;
}

Error:

annot convert type 'TSource' to 'TCastTo'

And why is this a runtime error?

public TCastTo CastMe<TSource, TCastTo>(TSource i)
{
     return (TCastTo)(object)i;
}

int a = 4;
long b = CastMe<int, long>(a); // InvalidCastException

// this contrived example works
int aa = 4;
int bb = CastMe<int, int>(aa);

// this also works, the problem is limited to value types
string s = "foo";
object o = CastMe<string, object>(s);

I've searched SO and the internet for an answer to this and found lots of explanations on similar generic related casting issues, but I can't find anything on this particular simple case.

解决方案

Why is this a compile time error?

The problem is that every possible combination of value types has different rules for what a cast means. Casting a 64 bit double to a 16 bit int is completely different code from casting a decimal to a float, and so on. The number of possibilities is enormous. So think like the compiler. What code is the compiler supposed to generate for your program?

The compiler would have to generate code that starts the compiler again at runtime, does a fresh analysis of the types, and dynamically emits the appropriate code.

That seems like perhaps more work and less performance than you expected to get with generics, so we simply outlaw it. If what you really want is for the compiler to start up again and do an analysis of the types, use "dynamic" in C# 4; that's what it does.

And why is this a runtime error?

Same reason.

A boxed int may only be unboxed to int (or int?), for the same reason as above; if the CLR tried to do every possible conversion from a boxed value type to every other possible value type then essentially it has to run a compiler again at runtime. That would be unexpectedly slow.

So why is it not an error for reference types?

Because every reference type conversion is the same as every other reference type conversion: you interrogate the object to see if it is derived from or identical to the desired type. If it's not, you throw an exception (if doing a cast) or result in null/false (if using the "as/is" operators). The rules are consistent for reference types in a way that they are not for value types. Remember reference types know their own type. Value types do not; with value types, the variable doing the storage is the only thing that knows the type semantics that apply to those bits. Value types contain their values and no additional information. Reference types contain their values plus lots of extra data.

For more information see my article on the subject:

http://ericlippert.com/2009/03/03/representation-and-identity/

这篇关于泛型:铸造和值类型,这是为什么违法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆