C#或.NET中见过的最奇怪的角落案例是什么?

我收集了几个角落案例和脑筋急转弯,并且总是希望听到更多。 该页面只包含C#语言位和bobs,但我也发现核心.NET的东西也很有趣。 例如,这里有一个不在页面上,但我觉得令人难以置信:

string x = new string(new char[0]);
string y = new string(new char[0]);
Console.WriteLine(object.ReferenceEquals(x, y));

我希望打印False - 毕竟,“新”(带有引用类型)总是会创建一个新对象,不是吗? C#和CLI的规范都表明它应该。 那么,不是在这种特殊情况下。 它打印True,并在我测试过的每个框架版本上完成。 (我还没有尝试过单声道,无可否认......)

要明确一点,这只是我正在寻找的那种事物的一个例子 - 我并不特别寻找这种古怪的讨论/解释。 (这与正常的字符串实习不一样;特别是,当调用构造函数时,字符串实习通常不会发生。)我确实要求类似的奇怪行为。

潜伏在那里的任何其他宝石?


我想我以前给你看过这个,但我喜欢这里的乐趣 - 这需要一些调试来追踪! (原始代码显然更加复杂和微妙......)

    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()不能; 所以它被施放(盒装)到对象(并因此为空)来调用object.GetType()...,其调用null; -p


更新:情节变厚... Ayende Rahien在他的博客上抛出类似的挑战,但是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 。 现在去洗你的眼睛!


银行家圆桌会议。

这不是一个编译器错误或故障,但肯定是一个奇怪的角落案例...

.Net框架采用称为银行家舍入的计划或四舍五入。

在银行家的四舍五入中,0.5的数字四舍五入到最接近的偶数,所以

Math.Round(-0.5) == 0
Math.Round(0.5) == 0
Math.Round(1.5) == 2
Math.Round(2.5) == 2
etc...

这可能会导致财务计算中出现一些意外的错误,这些错误基于更为人熟知的Round-Half-Up舍入。

Visual Basic也是如此。


如果调用Rec(0) (不在调试器下),该函数会执行什么操作?

static void Rec(int i)
{
    Console.WriteLine(i);
    if (i < int.MaxValue)
    {
        Rec(i + 1);
    }
}

回答:

  • 在32位JIT上它应该导致StackOverflowException
  • 在64位JIT上,它应该将所有数字打印到int.MaxValue
  • 这是因为64位JIT编译器会应用尾部调用优化,而32位JIT则不会。

    不幸的是,我没有一个64位机器来验证这一点,但该方法确实满足所有的尾部优化优化条件。 如果有人有,我会有兴趣看看是否属实。

    链接地址: http://www.djcxy.com/p/52949.html

    上一篇: What's the strangest corner case you've seen in C# or .NET?

    下一篇: An Unknown feature in C# Maybe Just For Me