71

私は何か間違ったことをしていますか、それとも次のコードは本当に不可能ですか?

dynamic x = new ExpandoObject { Foo = 12, Bar = "twelve" };

これが本当に不可能な場合、ExpandoObject を 2 つのプロパティでインスタンス化する別の 1 行の方法はありますか?

C# チームが、通常のオブジェクト、匿名オブジェクト、および列挙型/リストと同じ初期化構文を許可しないことを選択したのはなぜですか?

アップデート

この質問をしたのは、Pearl 愛好家に C# のクールな新しい動的機能を見せようとしたためでしたが、ExpandoObject. Hans Passant の回答のおかげで、それExpandoObjectがこの仕事には不適切なツールだったことに気付きました。私の本当の目標は、C# の動的機能を使用して、メソッドから 2 つの名前付きの値を返すことでした。Hans が指摘するように、dynamicキーワードはこれに最適です。ExpandoObjectこれを行うために、すべてのオーバーヘッドを伴うは必要ありませんでした。

したがって、メソッドから名前付きの値のペアを返したいが、型の安全性、Intellisense、リファクタリング、またはパフォーマンスを気にしない場合、これは非常にうまく機能します。

public dynamic CreateFooBar()
{
    return new { Foo = 42, Bar = "Hello" };
}

使用法:

dynamic fooBar = CreateFooBar();
var foo = fooBar.Foo;
var bar = fooBar.Bar;
4

7 に答える 7

55

私は何か間違ったことをしていますか、それとも次のコードは本当に不可能ですか?

それは本当に不可能です。代入演算子の左側にあるものは、コンパイル時に既知のプロパティまたはフィールドである必要がありますが、expando オブジェクトの場合は明らかにそうではありません。

C# チームが、通常のオブジェクト、匿名オブジェクト、および列挙型/リストと同じ初期化構文を許可しないことを選択したのはなぜですか?

質問の言い方は、論理エラーを示しています。機能はデフォルトでは実装されておらず、ほとんどすべての機能を許可しないようにしています。機能はデフォルトでは実装されておらず、機能させるには実装する必要があります。

機能を実装するための最初のステップは、最初に誰かが考えなければならないことです。私の知る限り、私たちは決してしませんでした。特に、2006 年にオブジェクト初期化子を設計していた人が、2010 年に言語に「動的」を追加し、それに応じて機能を設計する予定であることを知ることは非常に困難でした。機能は常に、時間を遡るのではなく、時間を進める設計者によって設計されます。私たちは未来ではなく、過去だけを覚えています。

とにかく、それは素晴らしいアイデアですので、共有していただきありがとうございます。誰かがそれを考えたので、それが限られた予算を費やすことができる最良のアイデアであるかどうかの決定、設計、仕様の作成、実装、テスト、文書化、およびそれを顧客に出荷します。

私は、そのようなことがすぐに起こるとは思っていません。先週の Build で発表した、この非同期と WinRT のビジネス全体で少し忙しくしています。

于 2011-09-19T22:34:05.690 に答える
43

ExpandoObject より優れたマウス トラップがあります。dynamicキーワードは、無名型を適切に処理します。

class Program {      
    static void Main(string[] args) {
        dynamic x = new { Foo = 12, Bar = "twelve" };
        Display(x);
    }
    static void Display(dynamic x) {
        Console.WriteLine(x.Foo);
        Console.WriteLine(x.Bar);
    }
}

不幸な問題の 1 つは、C# コンパイラが匿名型を生成し、メンバーに内部アクセスのみを与えることです。つまり、別のアセンブリのメンバーにアクセスしようとすると、ランタイム エラーが発生します。残念。

C# v7 で大幅に改善された Tupleを考えてみましょう。

于 2011-09-20T00:50:32.773 に答える
10

Dynamitey(オープンソースPCLで、nugetにあります)には、インラインにできるエキスパンドを初期化するための構文があります。

 //using Dynamitey.DynamicObjects
 var x = Build<ExpandoObject>.NewObject(Foo:12, Bar:"twelve");
于 2011-09-19T23:46:55.793 に答える