やりたいこととしてはインデクサのセッターでvalueがIEnumerableを継承しているかどうかによって分岐させたいのですができないということです.
C#
1 2using System; 3using System.Collections.Generic; 4 5namespace test 6{ 7 class Program 8 { 9 static void Main(string[] args) 10 { 11 var a = new A(); 12 a["aaa"] = 1;// case1 13 a["aaa"] = new int[] { 1 };//case2 14 } 15 } 16 17 class A 18 { 19 dynamic val; 20 21 public dynamic this[string key] 22 { 23 get { return 1; } 24 set { 25 26 if (value is IEnumerable<object>) 27 { 28 this.val = value; 29 Console.WriteLine("set IEnumerable"); 30 } 31 else 32 { 33 this.val = value; 34 Console.WriteLine("set Value"); 35 } 36 37 } 38 39 } 40 } 41}
case2では奇妙なことにVisualStudioでデバッグ時にウォッチ式やイミディエイトウィンドウで確認すると value is IEnumerable<object>はTrueと表示されるのですが,実行結果はFalseになってしまいます。直感的にもvalue is IEnumerable〈object〉はtrueだと思うのですが、コードでは判定はfalseです。
setter内でvalueがIEnumerable<object>かどうか判別し分岐する方法はあるのでしょうか?また何故,VisualStudioではTrueになるのでしょうか?
追記:
そもそも value is IEnumerable<object>でvalueがIEnumerableを実装しているかを判別できませんでした.string[]ではtrueになるので勘違いしたまま覚えておりました.
> VisualStudioでは value is IEnumerable<object>はTrueと表示される
この部分が意味不明。
デバッグ実行時のオブジェクトインスペクタの評価結果の話をしてるのか、それとも何か他の独自解釈をしてるのか判断できない。
デバッグ時にウォッチ式やイミディエイトウィンドウで実行した場合にtrueとなるという意味です。
ちょっと読み間違えていたのでコメント編集します。dynamic だからでは?
https://ufcpp.net/study/csharp/sp4_dynamic.html
> その他の場合、「リフレクション」を使ってメンバーを持っているかどうか調べて、持っているならそのメンバーにアクセスするコードを生成。
> 直感的にもvalue is IEnumerable〈object〉はtrueだと思うのですが
インデクサでの使用は関係なく単純に false になるはずです。
例えば、インデクサとかは除去して単純に、
var value = new int[] { 1 };
if (value is IEnumerable<object>) {}
は false になりますし、
IEnumerable<object> x = (IEnumerable<object>)value;
は 'int[] 型を IEnumerable<object> 型に変換できません' というコンパイル時のエラーになります。私の質問への理解が根本的に違いますか?
この話に関係していたようですね。
ジェネリックの共変性と反変性
https://docs.microsoft.com/ja-jp/dotnet/standard/generics/covariance-and-contravariance
"変性が適用されるのは参照型のみです。バリアント型パラメーターに対して値型を指定すると、その型パラメーターが、結果の構築型で不変になります"
質問のコードの int は値型なので変性が適用されないということになります。
ちなみに、int 型に代えて string 型の配列にすれば期待した結果 (true) になるはずです。
ご回答ありがとうございます.確かにstring[]だとtrueになります.
そもそもある変数をvalue is IEnumerable<object>で判別できると思っていたので私の解釈に誤りがありました.
回答2件
あなたの回答
tips
プレビュー