拡張メソッドと動的オブジェクト


96

問題を次のコードスニペットに要約します。

List<int> list = new List<int>() { 5, 56, 2, 4, 63, 2 };
Console.WriteLine(list.First());

上記のコードは正常に動作しています。

今私は以下を試しました

dynamic dList = list;
 Console.WriteLine(dList.First());

しかし、RuntimeBinderExceptionが発生しています。なぜそうなのですか?


これは、この質問の重複のように思えるがわずか4日前に尋ねたstackoverflow.com/questions/5270782/...
jbtule

@jbtule違いは、thisここでは動的であることですが、ここに着陸した場合は、おそらくその質問も検討する必要があります
nik.shornikov

ほとんどこれは動的キーワード
-in

回答:


131

Stecyaの答えを拡張するには...拡張メソッドは、拡張メソッドの形式での動的型付けではサポートされていません。つまり、インスタンスメソッドのように呼び出されます。ただし、これは機能します。

dynamic dList = list;
Console.WriteLine(Enumerable.First(dList));

もちろん、それが役立つ場合と役に立たない場合があります。動的タイピングを使用する理由と方法についてさらに詳しい情報を提供していただければ、さらに役立つ可能性があります。


私は動的オブジェクトで遊んでいて、この例外が発生しました。動的オブジェクトを使用する場所または使用しない場所について、このトピックに関する記事を書いていますか
santosh sing 2015年

19
@geek:個人的には、私の経験則はdynamic本当に必要な場所でのみ使用することです...基本的に、他の方法でリフレクションでメンバーにアクセスする場合、それは大きな兆候です。一方、私はハードな静的タイパーです-他の人はそれほど悲観的なポリシーを提案しないかもしれません:)
Jon Skeet

2
既知のタイプにキャストバックする方が読みやすいかもしれませんが、これは機能します。Console.WriteLine(((List <int>)dList).First()); またはConsole.WriteLine((dList as List <int>)。First());。
AVee

138

Jonの答えを拡張すると、これが機能しない理由は、通常の非動的コード拡張メソッドでは、コンパイラーが認識しているすべてのクラスを完全に検索して、一致する拡張メソッドを持つ静的クラスを探すためです。検索は、名前空間のネストとusing各名前空間で使用可能なディレクティブに基づいて順番に行われます。

つまり、動的拡張メソッドの呼び出しを正しく解決するために、なんらかの理由、DLRは実行時にすべての名前空間のネストとusingディレクティブがソースコードに含まれていたことを知る必要があります。そのすべての情報を呼び出しサイトにエンコードするための便利なメカニズムはありません。そのようなメカニズムを発明することを検討しましたが、コストが高すぎて、それに見合うだけのスケジュールリスクが多すぎると判断しました。


説明ありがとうございました。
santosh sing 2015年

3
そのような特徴は沖にありますか?それは確かに重大な変化でしょう。現在RunTimeBinderExceptionsをスローしている呼び出しは、ソースの再コンパイル時に突然動作し始めます。また、そのような機能の実装に関連するセキュリティリスクはありますか?
Ani

5
@ani:その機能の実装を計画していますか?いいえ。セキュリティ上のリスクはありますか? 私は何も知りません。どのようなセキュリティリスクを考えましたか?攻撃者は誰であり、ユーザーに対してどのような脅威を与えているかを言うことから始めます。
エリックリッペルト

@EricLippert、私はすべてのdynamicオブジェクトがC#:と等しいことを理解しました。したがって、DynamicObjectそれらを区別する方法はなく、拡張メソッドをdynamicに追加できない理由の1つです。そうですか?
Tom Sarduy、2012年

@EricLippertは、この回答をもう少し拡張し、「パラメーターのいずれかが動的である場合、すべての解決は実行時まで延期される」という文章に沿って文章を追加することを検討します。あなたにとってこの重要なビットはSOの他の場所で見つけるのは難しいですが(たとえば、stackoverflow.com
/ questions / 48324768を

18

First()方法ではないのでList。これは、Linq拡張で定義されています。IEnumerable<>

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.