2008年06月20日
川俣晶の縁側ソフトウェア技術雑記total 11191 count

デリゲート型フィールドをラムダ式で初期化する際のメンバ参照可能・不可能の違い

Written By: 川俣 晶連絡先

 ちょっと悩ましい問題に気付いたのでメモっておきます。

 対象はC# 3.0です。

 メモなので用語等不適切かもしれません。

デリゲート型フィールドをラムダ式で初期化する §

 リスト1は通るコードです。

 コンストラクタでデリゲート型フィールドをラムダ式で初期化しています。

リスト1 コンストラクタで初期化 §

using System;

class A

{

    private int x = 0;

    public Action d;

    public A()

    {

        d = () =>

            {

                Console.WriteLine(x);

            };

    }

}

class Program

{

    static void Main(string[] args)

    {

        A a = new A();

        a.d();

    }

}

初期化式を移動させる §

 ラムダ式をコンストラクタからフィールドを直接初期化する位置に移動させると、コンパイルが通らなくなります。

リスト2 フィールドを直接初期化 §

using System;

class A

{

    private int x = 0;

    public Action d = () =>

    {

        Console.WriteLine(x);

    };

}

class Program

{

    static void Main(string[] args)

    {

        A a = new A();

        a.d();

    }

}

エラー 1 フィールド初期化子は、静的でないフィールド、メソッド、またはプロパティ 'A.x' を参照できません d:\w\test\ConsoleApplication73\ConsoleApplication73\Program.cs 8 27 ConsoleApplication73

何が問題なのか §

 リスト1はthisをキャプチャしているからメンバにアクセスでき、リスト2はキャプチャすべきthisが無いからメンバにアクセスできない、という話ではないようです。Reflectorで見る限り、キャプチャという手順無しでthisへのアクセスは可能になっているようです。(デリゲート型はインスタンスの情報を持つので、それを経由すれば上位環境のthisをラムダ式に引き継げる……のだと思う。たぶん)

 つまり、初期化タイミングが違うだけで、メンバにアクセスできる、できないの差が出ます。

別の例 §

 オブジェクトの初期化構文を使っても、やはり初期化はできませんが、理由は違います。このラムダ式はクラスBではなくクラスCに含まれるので、そもそもBに対するthisはあり得ません。

リスト3 オブジェクトの初期化構文を使う §

using System;

class B

{

    public int x = 0;

    public Action SomeMethod;

}

class C

{

    public B b = new B()

        {

            SomeMethod = () =>

                {

                    Console.WriteLine(x);

                },

        };

}

class Program

{

    static void Main(string[] args)

    {

        C c = new C();

        c.b.SomeMethod();

    }

}

エラー 1 エラー 1 名前 'x' は現在のコンテキスト内に存在しません。 d:\w\test\ConsoleApplication75\ConsoleApplication75\Program.cs 18 39 ConsoleApplication75

で、何が問題なの? §

 当面は以上の確認とメモだけ。

Facebook

キーワード【 川俣晶の縁側ソフトウェア技術雑記
【技術雑記】の次のコンテンツ
2008年
07月
30日
ActionScript 3.0 (AS3)のRENDERイベントとinvalidateの悩ましい関係
3days 0 count
total 8808 count
【技術雑記】の前のコンテンツ
2008年
06月
15日
WindowsのコンソールはLFのみで復帰改行する(?)
3days 0 count
total 4102 count

このコンテンツを書いた川俣 晶へメッセージを送る

[メッセージ送信フォームを利用する]

メッセージ送信フォームを利用することで、川俣 晶に対してメッセージを送ることができます。

この機能は、100%確実に川俣 晶へメッセージを伝達するものではなく、また、確実に川俣 晶よりの返事を得られるものではないことにご注意ください。

このコンテンツへトラックバックするためのURL

https://mag.autumn.org/tb.aspx/20080620161831
サイトの表紙【技術雑記】の表紙【技術雑記】のコンテンツ全リスト 【技術雑記】の入手全リスト 【技術雑記】のRSS1.0形式の情報このサイトの全キーワードリスト 印刷用ページ

管理者: 川俣 晶連絡先

Powered by MagSite2 Version 0.36 (Alpha-Test) Copyright (c) 2004-2021 Pie Dey.Co.,Ltd.