1. ホーム
  2. c#

[解決済み】C#や.NETで見た最も奇妙なコーナーケースは何ですか?[解決済み]

2022-03-27 18:40:13

質問

角材を集めたり ブレイン・ティーザー また、いつでも聞いてください。このページではC#言語の断片的な情報しか扱っていませんが、.NETのコアな部分も興味深いと思っています。例えば、このページには載っていないのですが、信じられないようなことがあります。

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

私はこれがFalseと表示されることを期待します - 結局のところ、"new" (参照タイプで) 常に は新しいオブジェクトを作成しますよね?C#とCLIの両方の仕様では、そうなっています。 しかし、このケースではそうではありません。私がテストしたフレームワークのすべてのバージョンで、Trueと表示された。(確かにMonoでは試していないのですが...)

はっきりさせておきたいのは、これは私が探している種類のものの一例に過ぎないということです。私は特にこの奇妙さについての議論や説明を探していたわけではありません。(これは通常の文字列の相互作用とは異なります。特に、文字列の相互作用は通常コンストラクタが呼ばれたときには起こりません)。私は本当に似たような奇妙な動作について尋ねていたのです。

他に何か逸品が潜んでいませんか?

解決方法は?

これは以前にも紹介したと思いますが、私はこの面白さが好きです - これを突き止めるには、いくつかのデバッグが必要でした (元のコードは明らかにもっと複雑で微妙なんですが...)

    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()を呼び出すために、object(つまりnull)にキャスト(ボックス化)されます・・・これは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 . さあ、目を洗ってきてください。