質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.37%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Mono

Monoは、Ecma標準に準じた.NET Framework互換の環境を実現するためのオープンソースのソフトウェア群です。Linux、Mac OS X、Windowsなど多くのプラットフォームで動作します。その他にも、特定プラットフォーム向けに特化したサブプロジェクトも存在します。

.NET Framework

.NET Framework は、Microsoft Windowsのオペレーティングシステムのために開発されたソフトウェア開発環境/実行環境です。多くのプログラミング言語をサポートしています。

Q&A

解決済

3回答

8291閲覧

[C#] 引数にList<IHoge>を取るコンストラクタにList<HogeImpl>を渡せない

search_search

総合スコア187

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Mono

Monoは、Ecma標準に準じた.NET Framework互換の環境を実現するためのオープンソースのソフトウェア群です。Linux、Mac OS X、Windowsなど多くのプラットフォームで動作します。その他にも、特定プラットフォーム向けに特化したサブプロジェクトも存在します。

.NET Framework

.NET Framework は、Microsoft Windowsのオペレーティングシステムのために開発されたソフトウェア開発環境/実行環境です。多くのプログラミング言語をサポートしています。

1グッド

1クリップ

投稿2016/07/12 16:24

編集2016/07/12 18:15

こういうことがしたいのですが、エラーが出てしまいます。

C#

1interface IHoge {} 2 3class Hoge : IHoge {} 4 5class HogeHolder 6{ 7 public HogeHolder(List<IHoge> hogeList) 8 { 9 //... 10 } 11} 12 13class Program 14{ 15 static void Main(string[] args) 16 { 17 var list = new List<Hoge>(); 18 list.Add(new Hoge()); 19 var holder = new HogeHolder(list); 20 } 21}

以下のようなエラーが出ます。

The best overloaded method match for `HogeHolder.HogeHolder(System.Collections.Generic.List<IHoge>)' has some invalid arguments

Listを通さない場合はエラーなく通ります。

C#

1class HogeHolder 2{ 3 public HogeHolder(<IHoge> hoge) 4 { 5 //... 6 } 7} 8 9class Program 10{ 11 static void Main(string[] args) 12 { 13 var hoge = new Hoge(); 14 var holder = new HogeHolder(hoge); 15 } 16}

HogeHolderを、IHogeを下限とするジェネリクスのクラスにすれば、多分コンパイルは通るのかと思いますが、特にジェネリクスである必要のないクラスなので、それはしたくありません。

メソッドのように、引数から型パラメータを推測できれば、不必要な型パラメータ指定する必要がないので構わないのですが、コンストラクタの場合はできないようですね。。。

どうしたらいいのでしょうか?

--追記--
環境はMonoであり、純粋な.NETではありません。.NET環境では、HogeHolderの引数をIEnumerableにすることで、エラーなくコンパイルできました。

mondaminZ👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

解決法ではないですが、どうしてエラーになるのか?という点について回答してみます。

例えば、こんなクラスがあるとします。

csharp

1class Hoge2 : IHoge {}

このとき、以下のコードは正しいですね。

csharp

1class HogeHolder 2{ 3 public HogeHolder(List<IHoge> hogeList) 4 { 5 hogeList.Add(new Hoge2()); // IHogeのListに、IHogeを実装しているHoge2を挿入 6 //... 7 } 8}

では、このコードを実行しようとするとどうなるでしょうか。

csharp

1static void Main(string[] args) 2{ 3 var list = new List<Hoge>(); // HogeのList 4 list.Add(new Hoge()); 5 var holder = new HogeHolder(list); // HogeのListに、Hoge2を挿入!! 6}

投稿2016/07/13 06:01

tamoto

総合スコア4228

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

ベストアンサー

C#

1var list = new List<Hoge>();

↑を↓に変えてみてください。

C#

1var list = new List<IHoge>();

投稿2016/07/12 16:29

編集2016/07/12 16:31
Zuishin

総合スコア28662

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

search_search

2016/07/12 17:02

回答ありがとうございます。コンパイル通りました! ただ、なぜList<Hoge>のままだとうまくいかなかったのでしょうか? 追加要件で申し訳ないのですが、ProgramクラスからはあくまでHogeを使いたいので、取り出す際にダウンキャストする必要が生じてしまいます。 オブジェクト指向の原則のひとつである、リスコフの置換原則では、SがTの派生型であるとき、プログラム中でTが使われている個所をSで置換しても、妥当性は損なわれない、とありますし、 Javaだと、同様のコードはList<Hoge>のままでコンパイルは通ります。 C#が独特なのでしょうか?
Zuishin

2016/07/12 22:13

Q なぜ List<Hoge> のままだとうまくいかないのか? A IHoge は Hoge の下位互換ですが、List<IHoge> は List<Hoge> の下位互換ではないからです。 Q Program からはあくまで Hoge を使いたいのだが A それなら List<IHoge> ではなく List<Hoge> を使うべきです。でないと無用なキャストが生じる上に Hoge 以外のものが入る可能性を考慮しなくてはならなくなります。 Q Java だとコンパイルは通る A 通りません。ArrayList<IHoge> list = new ArrayList<Hoge>(); はコンパイルエラーになりました。
Zuishin

2016/07/12 22:25

Q IEnumerable にしても Mono だと通らない A https://ideone.com/ktPKvo 通りました。IEnumerable にする場所をお間違えになったかと。
guest

0

List<T> は要素の追加が可能なクラスだからです。
たとえばこういうコードが動いてしまったら困りますよね。

C#

1interface IHoge {} 2 3class Hoge : IHoge {} 4class Hoge2 : IHoge {} 5 6class HogeHolder 7{ 8 public HogeHolder(List<IHoge> hogeList) 9 { 10 // hogeList は実際には List<Hoge> なのに Hoge2 を入れられてしまってはまずい… 11 hogeList.Add(new Hoge2()); 12 } 13}

HogeHolder の側で要素の追加をしないのであれば、IEnumerable<IHoge> にすれば大丈夫です。

投稿2016/07/12 17:21

aetos

総合スコア42

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

search_search

2016/07/12 17:40

回答ありがとうございます。HogeHolderで要素は追加しないのですが、うまくいきませんでした。同様のエラーが出てしまいます。 The best overloaded method match for `HogeHolder.HogeHolder(System.Collections.Generic.IEnumerable<IHoge>)' has some invalid arguments ところで、 >hogeList は実際には List<Hoge> なのに Hoge2 を入れられてしまってはまずい… あくまで私のケースですが、インターフェースさえ統一されていれば、実際の型が混在していても、不都合はありません。
aetos

2016/07/12 17:51

> 同様のエラーが出てしまいます。 むむ。VS2015 で試したら、IEnumerable<IHoge> なら受け取れるんですけどね。 Mono 特有の事情でしょうか。そうなるとわかりません。 > インターフェースさえ統一されていれば、実際の型が混在していても、不都合はありません。 であれば Main の側を List<IHoge> にすればよいのではないでしょうか。 > ProgramクラスからはあくまでHogeを使いたいので、取り出す際にダウンキャストする必要が生じてしまいます。 という話と矛盾しているように思えます。
search_search

2016/07/12 18:12

Monoでない環境で試したところ、IEnumerableを使うことでコンパイルできるようになりました。おっしゃる通りMonoが関係しているかもしれません。これをヒントにもう少し調べてみます。ありがとうございます。 >矛盾しているように思えます。 たしかによく考えると矛盾していました。失礼しました。 HogeHolder側としてはIHogeで十分だったのですが、Main側からはHogeを使うのであれば、結局中身はHogeに限定されますね。。。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.37%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問