Feedback
Nullable<T>类型box成object的时候,就会变成null.
回复 引用 查看
@Lostinet
这么说来,我的这句"同样,任何重载比较运算的类(该类对于 null 比较与原始方式不同),也会有此类问题。"就是错误的了。
感谢指教。
已修改。
回复 引用 查看
大牛啊!!!!!
我刚刚就遇到这个问题了..........
希望请教一个问题就是
我声明一个泛型方法 ,希望返回一个C#基本Structure类型或实体对象
public T SelectOne<T> (string sql){.......}
假如T是Class我可以 T obj=new T();
那么T是Structure呢,
而且2者一个需要构造函数,一个不需要,而且Sturcture类型不同初始值也不同,怎么办?
我就想用Nullable来解决,但不知道怎么搞.苟请赐教
回复 引用 查看
2007-11-12 19:36 |
是啊
回复 引用
2007-11-12 19:36 |
分析得好,支持。。。
回复 引用
2007-11-12 20:37 |
博主,你的分析似乎有点问题。我们用ILDASM 查看你那段代码。
.locals init ([0] class [mscorlib]System.Reflection.PropertyInfo propHasValue,
[1] valuetype [mscorlib]System.Nullable`1<int32> example,
[2] bool hasValue)
IL_0000: nop
IL_0001: ldtoken valuetype [mscorlib]System.Nullable`1<int32>
IL_0006: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
IL_000b: ldstr "HasValue"
IL_0010: call instance class [mscorlib]System.Reflection.PropertyInfo [mscorlib]System.Type::GetProperty(string)
IL_0015: stloc.0 // 将 GetProperty() 结果存入 propHasValue
IL_0016: ldloca.s example // 将 example 地址压入计算堆栈
IL_0018: initobj valuetype [mscorlib]System.Nullable`1<int32> // 初始化 example 结构体
IL_001e: ldloc.0 // 将 propHasValue 变量压入计算堆栈
IL_001f: ldnull // 注意!传递给 GetValue() 方法的第一个对象是 null,而不是 example !!!!!
IL_0020: ldnull // 压入第二个参数
IL_0021: callvirt instance object [mscorlib]System.Reflection.PropertyInfo::GetValue(object, object[])
所以,我觉得编译器实际执行的代码应该是
bool hasValue = (bool)propHasValue.GetValue(null, null);
由于 "HashValue" 是实体方法,所以抛出你所说的异常。整个流程似乎没有调用 Nullable<T>.Equals()。不知道 Lostinet 是不是这个意思。
---------
另外,一个小小提醒。用 Lutz Reflector 看 IL 代码,最好把 Options > Disassembler > Optimization 改为 .NET 1.0,否则很容易引起误解。
回复 引用
@bidaas
引用类型可以用
T obj =new T();
结构类型可以
T obj = default(T);
可能需要加类型限定
public T SelectOne<T> (string sql) where T : struct{}
回复 引用 查看
@Q.yuhen
你说的没错
Lostinet 的那一句已经说的很清楚了。
不过 Nullable<T> 无法反射调用实例成员,这一点可以确定。
回复 引用 查看
这个问题也颇有意思,不过与Equals方法没有任何关系。
Lostinet说,Nullable<T>类型box成object的时候,就会变成null.
此话不严密,应该是:从未赋值的Nullable<T>类型box成object的时候,就会变成null。其实这个非常合理,不存在bug嫌疑。
int? x = new int?();
int? y = null;
int? z = new int?(1);
object o1 = x;
object o2 = y;
object o3 = z;
Assert.IsNull(o1);
Assert.IsNull(o2);
Assert.IsNotNull(o3);
Q.yuhen的结论完全是无厘头,怎么也不会压null到栈,除非你手工“优化”。
回复 引用 查看
@Zealic
“Nullable
无法反射调用实例成员”,有这个说法么?赋值的Nullable可以反射调用任何成员啊!
System.Reflection.PropertyInfo info = typeof(int?).GetProperty"HasValue");
int? x = new int?(1);
Assert.IsTrue((bool)info.GetValue(x, null));
你的问题说到底是给了空值来反射调用的缘故,与Nullable和反射特征毫无关系。
回复 引用 查看
@双鱼座
抱歉
口误,有值不会有问题。
文章里也说 “HasValue 为 false 时”
刚才忘了提了
回复 引用 查看
@Zealic
不是口误,根本是概念错误。
你的问题说到底是给了空值来反射调用的缘故,与Nullable的反射特征毫无关系。
回复 引用 查看
2007-11-12 23:28 |
to: 双鱼座
Q.yuhen的结论完全是无厘头,怎么也不会压null到栈,除非你手工“优化”。
建议你不要那么早下结论,自己去看看再说。
回复 引用
Nullable<>类型在CLR中有专门的作弊代码,使HasValue等于false的实例box后都等于null。想要Box等于Null的Nullable<>,只有使用StrongBox<>类型。
回复 引用 查看
int? example = null;
bool hasValue = (bool)propHasValue.GetValue(example, null);
我真搞不懂可以运行的思维是怎样的,example为null一看上去就是错误.
回复 引用 查看
我比较好奇的是:Equals什么时候调用的?
回复 引用 查看
@henry
example 实际上等同于 new Nullable<int>()
所以代码换成
PropertyInfo propHasValue = typeof(Nullable<int>).GetProperty("HasValue");
Nullable<int> example = new Nullable<int>();
bool hasValue = (bool)propHasValue.GetValue(example, null);
Console.WriteLine(hasValue);
也是同样的结果
@micYng
没有调用 Equals ,评论里已经说明白了
是因为 CLR 的特殊 boxing
回复 引用 查看
2007-11-13 18:00 |
扫盲
int?
是什么意思?
回复 引用
@Zealic
Nullable<int> example = new Nullable<int>(); 得到一个怎样的值?
这显然和Nullable<int> example 没有任何区别.
既然没有任何指向我理解不了(bool)propHasValue.GetValue(example, null); 是合法的.
既使是可以执行(bool)null会是一个怎样的结果,大家都非常清楚null是不可以向ValueType类型转换的.
回复 引用 查看
根据装配脑袋老大说的,CLR其实运行的就是(bool)propHasValue.GetValue(null, null);
所以才会抛错.
回复 引用 查看
2008-04-25 17:03 |
http://msdn2.microsoft.com/zh-cn/library/b05d59ty.aspx上面有GetValue的详细介绍
备注
这是为带有 DefaultChangeType 的 BindingFlags 参数、Binder 设置为 nullNothingnullptrnull 引用(在 Visual Basic 中为 Nothing)、CultureInfo 设置为 nullNothingnullptrnull 引用(在 Visual Basic 中为 Nothing) 的抽象 GetValue 方法提供实现的简便方法。
因为静态属性属于该类型,而不是单个对象,所以通过将 nullNothingnullptrnull 引用(在 Visual Basic 中为 Nothing) 作为对象参数传递来获取静态属性。例如,使用下面的代码获取 CultureInfo 的静态 CurrentCulture 属性:
复制代码
PropertyInfo CurCultProp =
(typeof(CultureInfo)).GetProperty("CurrentCulture");
Console.WriteLine("CurrCult: " +
CurCultProp.GetValue(null,null));
若要使用 GetValue 方法,请先获取类 Type。从 Type 获取 PropertyInfo。从 PropertyInfo 使用 GetValue 方法。
回复 引用
2008-04-25 17:20 |
再对比
string test = "abcdefghijklmnopqrstuvwxyz";
// To retrieve the value of the indexed Chars property using
// reflection, first get a PropertyInfo for Chars.
PropertyInfo pinfo = typeof(string).GetProperty("Chars");
// To retrieve an instance property, the GetValue method
// requires the object whose property is being accessed and an
// array of objects representing the index values.
// Show the seventh letter (g)
object[] indexArgs = { 6 };
object value = pinfo.GetValue(test, indexArgs);
Console.WriteLine(value);
// Show the complete string.
for (int x = 0; x < test.Length; x++)
{
Console.Write(pinfo.GetValue(test, new Object[] {x}));
}
我想无所谓可空与否 只要属性非静态 GetValue参数1就不可以为空
只有静态属性才可以 不知道对不对
看到这个帖子学了不少咚咚
回复 引用