C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[4]: IEnumerable<object>型への自動キャスト


(過去ログ 135 を表示中)

[トピック内 5 記事 (1 - 5 表示)]  << 0 >>

■79876 / inTopicNo.1)  IEnumerable<object>型への自動キャスト
  
□投稿者/ ぶなっぷ (83回)-(2016/05/26(Thu) 09:46:26)

分類:[.NET 全般] 

2016/05/26(Thu) 10:26:27 編集(投稿者)
以下のようなデータがあるときに、
  List<DataA> DataAList;
  List<DataB> DataBList;
  List<DataC> DataCList;

以下のようなメソッドを実装しました
  IEnumerable<object> GetCurrentDataList()
  {
    switch(DataType)  // DataTypeはenum型
    {
    case DataType.A: return DataAList.Select(x => (object)x);
    case DataType.B: return DataBList.Select(x => (object)x);
    case DataType.C: return DataCList.Select(x => (object)x);
    }
    return null;
  }

戻り値の型と正確に一致させるために、Select(x => (object)x)を実行する
ようにしていたのですが、昨日、ふと以下のコードでも、
コンパイルwarningすら表示されずに正常動作している(ように見える)こと
に気づきました。
  IEnumerable<object> GetCurrentDataList()
  {
    switch(DataType)  // DataTypeはenum型
    {
    case DataType.A: return DataAList;
    case DataType.B: return DataBList;
    case DataType.C: return DataCList;
    }
    return null;
  }

List → IEnumerable への自動キャスト と
DataA/DataB/DataC → object への自動キャストが同時に働いているもの
と推測されますが、これって安全なコードと言えるんでしょうか?

引用返信 編集キー/
■79877 / inTopicNo.2)  Re[1]: IEnumerable<object>型への自動キャスト
□投稿者/ Hongliang (431回)-(2016/05/26(Thu) 10:01:10)
ジェネリックの共変性とよばれるものです。
実体がList<string>であれば、IEnumerable<string>として扱えるのは自明です。
さて、IEnumerable<string>は、実際に使うときには
foreach (string value in enumerable)
のようになりますが、ここで
foreach (object value in enumerable)
と記述しても問題ないでしょう(もちろん、このforeach内でvalueに対してstringのメソッドを呼び出せなくなるとかはありますが)。
stringはobjectから派生しているので、個々の要素を親の型で扱っても良いと言うことですね。
つまり、このenumerableはIEnumerable<object>として扱っても型安全は守られることになります。
というのを言語レベルで認めているのが共変性(および反変性)です。
ジェネリックの他に配列とかでも認められています。
https://msdn.microsoft.com/ja-jp/library/dd799517.aspx

実際、DataType.AのときにGetCurrentDataList()を呼び出し、その返値をデバッガ等で確認すると、List<DataA>という型を維持しているのが分かります。
引用返信 編集キー/
■79883 / inTopicNo.3)  Re[2]: IEnumerable<object>型への自動キャスト
□投稿者/ ぶなっぷ (85回)-(2016/05/26(Thu) 11:37:40)
Hongliangさん

[ジェネリックの共変性]言葉は聞いたことがあるのですが、よく理解できていなかったようです。

今回のことでよく分かりました(^-^)

ありがとうございました。

解決済み
引用返信 編集キー/
■79884 / inTopicNo.4)  Re[3]: IEnumerable<object>型への自動キャスト
□投稿者/ 魔界の仮面弁士 (726回)-(2016/05/26(Thu) 11:56:03)
No79876 (ぶなっぷ さん) に返信
> switch(DataType) // DataTypeはenum型
> {
せめて、「switch (dataType) 」にした方が良いかと思いますよ。
文法的に正しくとも、「型名」と「変数名」を同じスペルにするのは混乱の元なので。



No79883 (ぶなっぷ さん) に返信
> [ジェネリックの共変性]言葉は聞いたことがあるのですが、よく理解できていなかったようです。

.NET 4 以降のバージョンであれば動作しますが、
.NET 2.0〜.NET 3.5 の場合は、コンパイルが通らないどころか
明示的型変換ですら失敗します(InvalidCastException)ので御注意あれ。
解決済み
引用返信 編集キー/
■79888 / inTopicNo.5)  Re[4]: IEnumerable<object>型への自動キャスト
□投稿者/ ぶなっぷ (86回)-(2016/05/26(Thu) 14:56:22)
魔界の仮面弁士さん

ありがとうございます。

> .NET 4 以降のバージョンであれば動作しますが、
> .NET 2.0〜.NET 3.5 の場合は、コンパイルが通らないどころか
>明示的型変換ですら失敗します(InvalidCastException)ので御注意あれ。
了解です、気をつけます。

> せめて、「switch (dataType) 」にした方が良いかと思いますよ。
> 文法的に正しくとも、「型名」と「変数名」を同じスペルにするのは混乱の元なので。
確かに、こうして掲示板で見ると紛らわしいですね。
Visual Studio上だと、型名と変数名は色が違うので、混乱しないので、いつの間にか
こうなっちゃいました。

C++時代に戻り、クラス名は先頭にC, enum型名は先頭にE とかつけるようにしようか
思案中です。

引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -