2

の制限は何ですか

public class A
{
     public string Stuff {get;set;}
}

...

repository.GetAll().Select(x=> new A { x.Stuff });

それはうまくいきません。追加する必要があります

{ Stuff = x.Stuff }

repository.GetAll().Select(x=> new { x.Stuff });

しかし、これは機能します。クラスAと非常によく似た定義を持つanonクラスを作成します。

概念的には、ここで起こっていることに大きな違いは見られません。誰かが光を当てますか?

4

2 に答える 2

3

簡単な答え-C#コンパイラと言語チームはそれをこのように実装しませんでした-彼らはそれを考えなかったか(ありそうもない)、またはそれは良い考えではないと判断しました...

repository.GetAll().Select(x=> new A { x.Stuff });

それはうまくいきません。追加する必要があります

これはオブジェクト初期化子です。これは、オブジェクトのデフォルトコンストラクターを呼び出してから、プロパティ名を値、つまり:Stuff = x.Fooに一致させることで機能します。これは、実際にはプロパティを一致させるための単なるショートカットであるため、構文は実際には次の「省略形」にすぎません。

A tmp = new A();
tmp.Stuff = x.Stuff;

さて、コンパイラチームは、方程式の左側がない初期化ステートメントで、名前が一致、型が暗黙的に変換可能な一致するプロパティを検索する必要があると想定できたと思いますが、これは「悪い考えのリストをいちゃつく「もしそれが言語チームによって議論されたであろうか、いつだったか。一般に、C#は構文がかなり明示的であり、これにより、2つの別々の一致(名前+タイプ)が必要な方法で少し緩められ、多くのシナリオで自明ではなくなります。ここではパブリックAPIを使用しているため( )、どちらの側(または任意のタイプの「x」)でも リファクタリングを行うのは非常に簡単です。AA

最後に、これも実際には必要ありません。Aのインスタンスをこのように構築する場合は、オーバーロードを使用してコンストラクターを追加し(どのような場合でも多くの点で安全です)、次を使用します。

repository.GetAll().Select(x=> new A(x.Stuff));

これにより、意図と意味が非常に明確になり、脆弱な保守性が失われます。

repository.GetAll().Select(x=> new { x.Stuff });

これはまったく異なることをしています。ここでは、匿名型を初期化し、コンパイラに型名と型を完全に決定させます。パブリックAPIを実際に使用したことがないため、これは「安全」であると判断されたと思います。匿名型は、定義されているメソッドから実際に「リーク」することは想定されていません。この場合、リファクタリングによってプロパティ名が変更され、値が効果的に変更されるなどのリスクが大幅に軽減され、単一のメソッドに分離されます。これにより、この「自動」命名機能のリスクが全体的に低くなります。また、匿名型でコンストラクターを定義できないため、ここでは簡単な代替手段はありません。したがって、この場合、簡潔な構文を作成する簡単な方法はありません。

于 2012-05-23T17:37:57.613 に答える
1

考えられる理由の1つ:リポジトリのアイテムの変更よりも実際の型に暗黙のプロパティ割り当てが許可される場合(つまりx.Stuff、名前が変更されるx.Other場合)、新しいプロパティがA.Stuffと一致しなくなるため、非常に驚​​くべき場所でコンパイル時エラーが発生します。

于 2012-05-23T17:26:43.423 に答える