泛型转换的问题,求解释

ayymbirst 2012-08-06 06:19:26
static void convert<T>(ref T t1) where T : struct
{
if (t1 is Enum)
{
T t2 = (T)Enum.Parse(typeof(T), "1");
T t3 = (T)Convert.ChangeType(1,Enum.GetUnderlyingType(typeof(T)));
T t4 = (T)(object)1;
}

}

在泛型示例中,这三句转换代码结果是一致的.
我得出的结论是:
这三句代码都是拆箱的过程(将 int 类型转换 object 然后转目标类型)

本人非常不理解 t2,t3 的转换方式.有点多此一举. 求解释.
...全文
280 17 打赏 收藏 转发到动态 举报
写回复
用AI写文章
17 条回复
切换为时间正序
请发表友善的回复…
发表回复
qldsrx 2012-08-07
  • 打赏
  • 举报
回复
[Quote=引用 14 楼 的回复:]
以上三种方式的区别:
string str = "2009/12/12";
DateTime dt = (DateTime)(object)str; //运行报错 [1]
DateTime dt1 = (DateTime)str; //编译不通过 [2]
DateTime now1 = (DateTime)Convert.Cha……
[/Quote]
看一个值类型是否可以转换到另一个值类型,你需要看他的定义,如果定义中不存在对应的强制类型转换则不可能实现,对于内置类型如int、long、float等,他们的类型转换也是内置的,所以不在定义中,DateTime不是内置类型,需要通过explicit或implicit来定义类型转换。
通过拆箱的方式达到类型转换的过程,其实是暗地里调用了强制类型转换的方法,如果不存在对应的类型转换函数,则拆箱过程将失败。
如果你对指针感兴趣,你上面的代码可以这样写:
unsafe
{
long a = 633961728000000000;
long* pa = &a;
DateTime* pb = (DateTime*)pa;
DateTime b = *pb;//这里输出将保证是“2009-12-12”的日期
}

如果你连IL编码都不会,指针操作都不知道,那么我劝你别在纠结下去了,再纠结下去只会走火入魔,必须有足够的基础知识才能理解它的运行原理,否则就先用着。
ayymbirst 2012-08-07
  • 打赏
  • 举报
回复
以上三种方式区别,(以下不是装箱与拆箱的示例,但能够说明以上三种转换的区别)
string str = "2009/12/12";
DateTime dt = (DateTime)(object)str; //运行报错 [1]
DateTime dt1 = (DateTime)str; //编译不通过 [2]
DateTime now1 = (DateTime)Convert.ChangeType(str, typeof(DateTime)); //通过 [3]
ayymbirst 2012-08-07
  • 打赏
  • 举报
回复
以上三种方式的区别:
string str = "2009/12/12";
DateTime dt = (DateTime)(object)str; //运行报错 [1]
DateTime dt1 = (DateTime)str; //编译不通过 [2]
DateTime now1 = (DateTime)Convert.ChangeType(str, typeof(DateTime)); //通过 [3]

装箱与拆箱能够实现数据类型转换,但不能解决所有的类型转换吧.
ayymbirst 2012-08-07
  • 打赏
  • 举报
回复
[Quote=引用 10 楼 的回复:]

引用 1 楼 的回复:
t2的转换方式有必要存在,是对字符串的转换,t3的方式没必要,t1也没有存在的必要。
这三句代码的转换结果是不同的,不可能相同。

我怎么觉得都是一路货呢?t2,t3,t4都是T,也都是从1变来的。

不过费这么大劲转换,意义何在?
[/Quote]
同感,我尝试解释一下.
Hirisw 2012-08-07
  • 打赏
  • 举报
回复
用Express lambda处理
ayymbirst 2012-08-07
  • 打赏
  • 举报
回复
你让我很纠结.我承认我很白痴,但你不能阻止我走向白痴的对立面.
qldsrx 2012-08-06
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 的回复:]
t2内部是通过t3 的实现方式实现自已的转换的.
t3 的转换核心是:
public static object ChangeType(object value, Type conversionType, IFormatProvider provider)
{
if (conversionType == null)
{
throw new ArgumentNullExcep……
[/Quote]
你明明都会看源码了,还来多此一问干嘛?将被调用函数分析一下,就知道其复杂性了,哪个效率最高很明显,这个不用我说了吧。本来为达到一个目的,方法很多,你要是想问为什么条条大路通罗马,这个我无法告诉你,事实如此,不过如果只有一种方法,也谈不上优化代码了。
bwangel 2012-08-06
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 的回复:]
t2的转换方式有必要存在,是对字符串的转换,t3的方式没必要,t1也没有存在的必要。
这三句代码的转换结果是不同的,不可能相同。
[/Quote]
我怎么觉得都是一路货呢?t2,t3,t4都是T,也都是从1变来的。

不过费这么大劲转换,意义何在?
ayymbirst 2012-08-06
  • 打赏
  • 举报
回复
t2内部是通过t3 的实现方式实现自已的转换的.
t3 的转换核心是:
public static object ChangeType(object value, Type conversionType, IFormatProvider provider)
{
if (conversionType == null)
{
throw new ArgumentNullException("conversionType");
}
if (value == null)
{
if (conversionType.IsValueType)
{
throw new InvalidCastException(Environment.GetResourceString("InvalidCast_CannotCastNullToValueType"));
}
return null;
}
IConvertible convertible = value as IConvertible;
if (convertible == null)
{
if (value.GetType() != conversionType)
{
throw new InvalidCastException(Environment.GetResourceString("InvalidCast_IConvertible"));
}
return value;
}
if (conversionType == ConvertTypes[3])
{
return convertible.ToBoolean(provider);
}
if (conversionType == ConvertTypes[4])
{
return convertible.ToChar(provider);
}
if (conversionType == ConvertTypes[5])
{
return convertible.ToSByte(provider);
}
if (conversionType == ConvertTypes[6])
{
return convertible.ToByte(provider);
}
if (conversionType == ConvertTypes[7])
{
return convertible.ToInt16(provider);
}
if (conversionType == ConvertTypes[8])
{
return convertible.ToUInt16(provider);
}
if (conversionType == ConvertTypes[9])
{
return convertible.ToInt32(provider);
}
if (conversionType == ConvertTypes[10])
{
return convertible.ToUInt32(provider);
}
if (conversionType == ConvertTypes[11])
{
return convertible.ToInt64(provider);
}
if (conversionType == ConvertTypes[12])
{
return convertible.ToUInt64(provider);
}
if (conversionType == ConvertTypes[13])
{
return convertible.ToSingle(provider);
}
if (conversionType == ConvertTypes[14])
{
return convertible.ToDouble(provider);
}
if (conversionType == ConvertTypes[15])
{
return convertible.ToDecimal(provider);
}
if (conversionType == ConvertTypes[0x10])
{
return convertible.ToDateTime(provider);
}
if (conversionType == ConvertTypes[0x12])
{
return convertible.ToString(provider);
}
if (conversionType == ConvertTypes[1])
{
return value;
}
return convertible.ToType(conversionType, provider);
}

装箱痕迹明显呀.
这与
T t4 = (T)(object)1; 很类似呀.
谁能告诉我,以下方法调用不算装箱?
public object(int i){
return i ;
}
ayymbirst 2012-08-06
  • 打赏
  • 举报
回复
拆箱.
ayymbirst 2012-08-06
  • 打赏
  • 举报
回复
OK , 口误 , 字符串 1 转object 不算装箱, object 转 T 算吧.
qldsrx 2012-08-06
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 的回复:]
引用 2 楼 的回复:

另外只有t4存在装箱拆箱的过程,另外2个则没有明显的动作(即使偷偷做了也看不出)。
t4是先将整数1装箱到O类型,然后按照T类型拆箱到值类型。
enum是值类型的,所有值类型都是可以这样拆箱的,因此对于任何的struct,这样写都成立,其效率也最高。

例如 enum.parse.....返回的是object 从数值1到object的转换不是装箱么?
t3更……
[/Quote]
你再看看清楚好不好,那个是数值1?明明是字符串1,字符串本身就是object的类型,哪里有装箱的过程?而且只要是调用函数的,即使函数内部有装箱过程也和你无关,要对比第三种方法,不是直接通过装箱后拆箱来转换的,就不能归类到那里,且性能肯定不高。
ayymbirst 2012-08-06
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 的回复:]

t2 Enum.Parse: 将一个或多个枚举常数的名称或数字值的字符串表示转换成等效的枚举对象。
意思就是将1这个值转换成对应的T枚举对象。
t3 Convert.ChangeType:返回一个指定类型的对象,该对象的值等效于指定的对象。
意思是返回一个类型为 Enum.GetUnderlyingType(typeof(T))的对象,其值等效于 1
[/Quote]
能举例说说区别么,比如性能上
bm1987215 2012-08-06
  • 打赏
  • 举报
回复
t2 Enum.Parse: 将一个或多个枚举常数的名称或数字值的字符串表示转换成等效的枚举对象。
意思就是将1这个值转换成对应的T枚举对象。
t3 Convert.ChangeType:返回一个指定类型的对象,该对象的值等效于指定的对象。
意思是返回一个类型为 Enum.GetUnderlyingType(typeof(T))的对象,其值等效于 1
ayymbirst 2012-08-06
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 的回复:]

另外只有t4存在装箱拆箱的过程,另外2个则没有明显的动作(即使偷偷做了也看不出)。
t4是先将整数1装箱到O类型,然后按照T类型拆箱到值类型。
enum是值类型的,所有值类型都是可以这样拆箱的,因此对于任何的struct,这样写都成立,其效率也最高。
[/Quote]
例如 enum.parse.....返回的是object 从数值1到object的转换不是装箱么?
t3更明显
qldsrx 2012-08-06
  • 打赏
  • 举报
回复
另外只有t4存在装箱拆箱的过程,另外2个则没有明显的动作(即使偷偷做了也看不出)。
t4是先将整数1装箱到O类型,然后按照T类型拆箱到值类型。
enum是值类型的,所有值类型都是可以这样拆箱的,因此对于任何的struct,这样写都成立,其效率也最高。
qldsrx 2012-08-06
  • 打赏
  • 举报
回复
t2的转换方式有必要存在,是对字符串的转换,t3的方式没必要,t1也没有存在的必要。
这三句代码的转换结果是不同的,不可能相同。

110,565

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧