我想我之前向您展示过这个,但我喜欢这里的乐趣 - 这需要一些调试才能找到! (原始代码显然更加复杂和微妙......)
static void Foo<T>() where T : new()
{
T t = new T();
Console.WriteLine(t.ToString()); // works fine
Console.WriteLine(t.GetHashCode()); // works fine
Console.WriteLine(t.Equals(t)); // works fine
// so it looks like an object and smells like an object...
// but this throws a NullReferenceException...
Console.WriteLine(t.GetType());
}
那么什么是T...
答案:任意Nullable<T>
- 例如int?
。所有方法都被重写,除了 GetType() 不能;因此它被强制转换(装箱)为对象(因此为 null)以调用 object.GetType()... 调用 null ;-p
更新:情节变得更加复杂……Ayende Rahien 扔下了一个他的博客上有类似的挑战 http://ayende.com/Blog/archive/2009/11/25/can-you-hack-this-out-hint-1.aspx,但有一个where T : class, new()
:
private static void Main() {
CanThisHappen<MyFunnyType>();
}
public static void CanThisHappen<T>() where T : class, new() {
var instance = new T(); // new() on a ref-type; should be non-null, then
Debug.Assert(instance != null, "How did we break the CLR?");
}
但它是可以被打败的!使用与远程处理等相同的间接方式;警告 - 以下是纯粹的邪恶:
class MyFunnyProxyAttribute : ProxyAttribute {
public override MarshalByRefObject CreateInstance(Type serverType) {
return null;
}
}
[MyFunnyProxy]
class MyFunnyType : ContextBoundObject { }
有了这个,new()
呼叫被重定向到代理(MyFunnyProxyAttribute
),它返回null
。现在去洗洗眼睛吧!