今日、
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のクラスでも質量につながるため)。