質問

C#4で修正されたバグにより、次のプログラムは true を出力します。 (LINQPadで試してください)

void Main() { new Derived(); }

class Base {
    public Base(Func<string> valueMaker) { Console.WriteLine(valueMaker()); }
}
class Derived : Base {
    string CheckNull() { return "Am I null? " + (this == null); }
    public Derived() : base(() => CheckNull()) { }
}

VS2008リリースモードでは、InvalidProgramExceptionがスローされます。 (デバッグモードでは、正常に動作します)

VS2010 Beta 2では、コンパイルされません(ベータ1は試しませんでした)。難しいことを学んだ

純粋なC#で this == null を作成する他の方法はありますか?

役に立ちましたか?

解決

この観察結果は、別のStackOverflowに投稿されました今日の質問

マークその質問に対する優れた回答は、仕様(セクション7.5.7)に従ってはいけないことを示していますそのコンテキストで this にアクセスできるようになりますが、C#3.0コンパイラでアクセスできるかどうかはバグです。 C#4.0コンパイラは仕様に従って正しく動作しています(ベータ1でも、これはコンパイル時エラーです):

  

&#167; 7.5.7このアクセス

     

A this-access は予約語 this で構成されています。

     

this-access:

this
     

A this-access は、インスタンスコンストラクター、インスタンスメソッド、またはインスタンスアクセサーのブロックでのみ許可されます。

他のヒント

デバッグモードバイナリの生の逆コンパイル(最適化なしのリフレクタ)は次のとおりです。

private class Derived : Program.Base
{
    // Methods
    public Derived()
    {
        base..ctor(new Func<string>(Program.Derived.<.ctor>b__0));
        return;
    }

    [CompilerGenerated]
    private static string <.ctor>b__0()
    {
        string CS$1
   .locals init (
        [0] string CS$1
    L_0000: ldloc.0 
    L_0001: call instance string CompilerBug.Program/Derived::CheckNull()
    L_0006: ret 
) L_0000: ldloc.0 L_0001: call instance string CompilerBug.Program/Derived::CheckNull() L_0006: stloc.0 L_0007: br.s L_0009 L_0009: ldloc.0 L_000a: ret
; CS$1<*> = CS$1<*>.CheckNull(); Label_0009: return CS$1<*>; } private string CheckNull() { string CS$1<*>; CS$1<*> = "Am I null? " + ((bool) (this == null)); Label_0017: return CS$1<*>; } }

CompilerGeneratedメソッドは意味がありません。 IL(下)を見ると、null string (!)でメソッドを呼び出しています。

<*>

リリースモードでは、ローカル変数は最適化されて除外されるため、存在しない変数をスタックにプッシュしようとします。

<*>

(C#に変換するとReflectorがクラッシュします)


編集:コンパイラーが ldloc を出力する理由を誰もが知っていますか(Eric Lippert?)

それはありました! (そして証拠も得た)

alt text

これは「バグ」ではありません。これは、型システムを乱用しています。現在のインスタンスへの参照( this )をコンストラクター内の誰かに渡すことは決してありません。

同様の&quot; bug&quot;を作成できます基本クラスコンストラクター内でも仮想メソッドを呼び出します。

悪意のあることを できるからといって、それを少しでも手に入れてもバグではありません。

間違っている可能性がありますが、オブジェクトが null である場合、 this が適用されるシナリオは決してありません。

たとえば、 CheckNull をどのように呼び出しますか?

Derived derived = null;
Console.WriteLine(derived.CheckNull()); // this should throw a NullReferenceException

これがあなたが探しているものかどうかわからない

    public static T CheckForNull<T>(object primary, T Default)
    {
        try
        {
            if (primary != null && !(primary is DBNull))
                return (T)Convert.ChangeType(primary, typeof(T));
            else if (Default.GetType() == typeof(T))
                return Default;
        }
        catch (Exception e)
        {
            throw new Exception("C:CFN.1 - " + e.Message + "Unexpected object type of " + primary.GetType().ToString() + " instead of " + typeof(T).ToString());
        }
        return default(T);
    }

example:UserID = CheckForNull(Request.QueryString [&quot; UserID&quot;]、147);

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top