C#の暗黙的に入力されたフィールド

今日、 Kytaで、C#にvarと呼ばれる暗黙的に型指定されたローカル変数がある理由について非常に興味深い質問が尋ねられましたが、暗黙的に型指定されたフィールドはありませんか?



実際、この状況は決して偶然ではありません。 それでは、コンパイラがこのように動作し、そうでない理由をいくつか見てみましょう。



まず、暗黙的に型指定されたローカル変数を宣言するためにvarを使用する機能は、独立した機能ではありませんでした。 C#言語を開発するとき、F#などの完全に暗黙的に型付けされたプログラミング言語を作成するという目標を設定する人はいません。 暗黙的な型指定は、今日では頭字語LINQで知られている、より一般的な概念の1つのコンポーネントにすぎません(重要ではありますが)。



LINQを開発するとき、既存の型のみに開発者を結びつけることは「悪」な制限であると判断されたため、開発者は匿名クラスのシーケンスを返す機会を与えられました。 その場合、暗黙的に型指定された変数を使用しないと、これは不可能です。



IEnumerable <Customer> customers = null ;

// , result ? IEnumerable<??>?

var result = from c in customers

where c.Age > 33

select new {c.Name, c.Age};



* This source code was highlighted with Source Code Highlighter .








ただし、型宣言でvarキーワードを使用しても、よりグローバルな目標を解決するのに役立ちません(これもLINQについてです)。



第二に、コンパイラ(*)がそのような機会を実現するのがどれほど難しいかを深く理解していなくても、その実装と使用にはいくつかの欠点があります。 最初の欠点は、暗黙的に型指定されたフィールドが匿名型の悪友になることです。



次のクラスを想像してみましょう。



public class Foo

{

public var someField = new {Name = "name" , Value = 12};

}



* This source code was highlighted with Source Code Highlighter .








.Netの匿名型は内部型として実装されるようになったため、現在のアセンブリの外部にこの型を「エクスポート」することはまったく不可能です。 もちろん、クラス内部またはプライベートフィールドに対してのみ暗黙的に型指定されたフィールドの使用を制限したり、匿名クラスで暗黙的に型指定されたフィールドの使用を禁止することもできますが、これにより、2つの意味的に類似したC#言語構造体の動作が大きく異なります。 C#3.0でvarが登場した理由の1つは、匿名型(LINQの有無にかかわらず)の使用です。ここでは、暗黙的に型指定されたフィールドは動作しません。



もう1つの重要な制限は、暗黙的に型指定されたフィールドが、初期化されたフィールドと「初期化子」の間の接続を近づきすぎることです。 例を見てみましょう: fooという「var」フィールドを含むクラスAがあるとします。これはクラスBの静的メソッドFooを呼び出すことで初期化されます。



public class A

{

public static var foo = B.Foo();

}



public class B

{

public static int Foo()

{

return default ( int );

}

}



* This source code was highlighted with Source Code Highlighter .








これにより、いくつかの追加の質問が導かれます。クラスAとクラスBが異なるアセンブリにある場合はどうなりますか? しかしアセンブリAを再コンパイルせずに、クラスB アセンブリが再コンパイルされ、 Fooメソッドの戻り値の型がintからstringに変更された場合はどうでしょうか? または、フィールドA. fooの型にバインドされた暗黙的に型指定されたフィールドC. foo (つまり、クラスCのフィールドfoo )、フィールドC. fooにバインドされたフィールドD. fooなどがまだあります。 1つの関数の戻り値の型を変更すると、1ダースの異なるクラス(**)のフィールドの型が変更されます。 とにかく、フィールドはローカル変数に比べてクラスの設計と実装の重要な部分です。したがって、誰かが3番目のモジュールの関数シグネチャを変更したからといって、このフィールドのようにオンザフライで変更するのは良い考えではありません。



もちろん、限られたケースでのみ暗黙的に型指定されたフィールドを使用する可能性を制限し、他のアセンブリの匿名型およびクラスでこの機能の使用を禁止し、たとえば現在のクラスのメソッドの使用のみを残すことができます。 しかし、この場合でも、この機能の実装には実装に多大な労力が必要です(Ericの証明、私はJとは何の関係もありません)。これにより、C#コンパイラ開発者が頭に抱える無限の改善リストの優先順位はかなり低くなります。



----------------------



(*)Eric Lippertがすでに記事「 なぜフィールドに変数がないのか」でこれを行ったので、荒野に入ることに意味はありません この中で、暗黙的に型付けされたフィールドの実装には、暗黙的に型付けされたローカル変数の実装よりも大幅に大きな実装コストが必要になるという事実について話しています。



(**)もちろん、これは指標ではなく、正しくまたは誤って使用する機会です。 しかし、このことの助けを借りて、「ケースのコードを記述しない方法」に示されている例が花としても表示されるように報酬を与えることができます(小さな変更は、1つのクラスではなく、他の12のクラスでも質量につながるため)。



All Articles