C#list <interface>:なぜ `list <ifoo> foo = new list <bar>();` -- c# フィールド と generics フィールド 関連 問題

C# List<Interface>: why you cannot do `List<IFoo> foo = new List<Bar>();`












64
vote

問題

日本語

インタフェースがある場合<コード> IFoo とクラス<コード> Bar : IFoo 、なぜ次のことができます。

<事前> <コード> List<IFoo> foo = new List<IFoo>(); foo.Add(new Bar());

しかしあなたはできません:

<事前> <コード> List<IFoo> foo = new List<Bar>();
英語

If you have an Interface IFoo and a class Bar : IFoo, why can you do the following:

List<IFoo> foo = new List<IFoo>();   foo.Add(new Bar()); 

But you cannot do:

List<IFoo> foo = new List<Bar>(); 
</div
     
 
 

回答リスト

132
 
vote
vote
ベストアンサー
 

カジュアルな一見の場合、このは(ビールのようにが自由にする必要がある)作業であるべきです。しかし、迅速な健全性チェックでは、なぜできない理由がわかります。次のコードはコンパイルではないことに注意してください。 がポイントまで大丈夫になっていても、それが許可されていない理由を示すことを目的としています。

<事前> <コード> public interface IFoo { } public class Bar : IFoo { } public class Zed : IFoo { } //..... List<IFoo> myList = new List<Bar>(); // makes sense so far myList.Add(new Bar()); // OK, since Bar implements IFoo myList.Add(new Zed()); // aaah! Now we see why. //.....

myList List<IFoo> です。つまり、 IFoo のインスタンスを取ります。ただし、これは List<Bar> としてインスタンス化されているという事実と矛盾しています。 me/home0 を持つことは、 me/home1 の新しいインスタンスを追加できることを意味しますが、基礎となるリストは実際に me/home2 であることを許可できません。これは<コード> me/home3 を収容できません。

 

At a casual glance, it appears that this should (as in beer should be free) work. However, a quick sanity check shows us why it can't. Bear in mind that the following code will not compile. It's intended to show why it isn't allowed to, even though it looks alright up until a point.

public interface IFoo { } public class Bar : IFoo { } public class Zed : IFoo { }  //.....  List<IFoo> myList = new List<Bar>(); // makes sense so far  myList.Add(new Bar()); // OK, since Bar implements IFoo myList.Add(new Zed()); // aaah! Now we see why.  //..... 

myList is a List<IFoo>, meaning it can take any instance of IFoo. However, this conflicts with the fact that it was instantiated as List<Bar>. Since having a List<IFoo> means that I could add a new instance of Zed, we can't allow that since the underlying list is actually List<Bar>, which can't accommodate a Zed.

</div
 
 
   
   
47
 
vote

その理由は、C#3.0以前のリリースでの一般的なジェネリックとコントラクティアンスをサポートしていないことです。これはC#4.0で実装されているので、次のことができるようになります。

<事前> <コード> me/home4

C#4.0では、IENUMERABLE&lt; ifoo&gtにキャストできますが、リスト&lt; ifoo&gt;リストをキャストできた場合は、その理由は安全性のためです。バー&gt;リスト&lt; ifoo&gt;あなたはリストに他のIFOO実装者を追加することができ、タイプの安全性を破ることができるでしょう。

C#での共分散と対照の背景については、Eric Lippertは素敵なブログシリーズ

 

The reason is that C# does not support co- and contravariance for generics in C# 3.0 or earlier releases. This is being implemented in C# 4.0, so you'll be able to do the following:

IEnumerable<IFoo> foo = new List<Bar>(); 

Note that in C# 4.0, you can cast to IEnumerable<IFoo>, but you won't be be able cast to List<IFoo>. The reason is due to type safety, if you were able to cast a List<Bar> to List<IFoo> you would be able to add other IFoo implementors to the list, breaking type safety.

For more background on covariance and contravariance in C#, Eric Lippert has a nice blog series.

</div
 
 
12
 
vote

リストを基本クラスまたはインターフェースのリストに変換する必要がある場合は、これを実行できます。

<事前> <コード> me/home5
 

If you need to convert a list to a list of a base class or interface you can do this:

using System.Linq;  ---  List<Bar> bar = new List<Bar>(); bar.add(new Bar());  List<IFoo> foo = bar.OfType<IFoo>().ToList<IFoo>(); 
</div
 
 
 
 
4
 
vote

リストの作成を行うことは、IFOOになるようにTを指定したことを指定しています。

をサポートしていても、異なる型であるため、バーとしてインスタンス化することはできません。
 

It is to do with the creation of the List, you have specified the T to be IFoo therefore you cannot instantiate it as a Bar since they are different types, even though Bar supports IFoo.

</div
 
 
1
 
vote

リストはこの場合のタイプで、継承質問リスト<; ifoo&gt;本当にリストとは異なります。リストはiFooまたはBarのいずれかの特性を知らないか、または受け継ぐ。

助けを願っています。

 

List is the type in this case and it's not an inheritance question List<IFoo> really is different than List<Bar>. List doesn't know anythign of, or inherit the characteristics of either IFoo or Bar.

Hope that helps.

</div
 
 
1
 
vote

List<Bar> List<IFoo>

から継承しません。
 

List<Bar> does not inherit from List<IFoo>

</div
 
 
1
 
vote

IFoo のリストには、 Bar sも含めることができますが、 IFoo s のリストも含めることができます。 / EM> <コード> Bar sのリストと同じこと。

C#を使用する代わりに、上記の英語を使用しました。これが深い問題ではないことを強調したいと思います。あなたは単なる構文の詳細によって混同されるだけです。答えを理解するためには、構文を超えて見る必要があり、それが実際に何を意味するのか考えてください。

IFoo のリストは、 Bar IFoo であるため、 Bar を含めることができます。ここで私たちはリストの要素について話しています。リストはまだ List<IFoo>0 sのリストです。それを変えていません。

List<IFoo>1 というリストは、まだ List<IFoo>2 sのリストです(より小児語的には、<コード>は<コード>として宣言されています。 List<IFoo>4 )。他には何もできません。特に、 List<IFoo>5 S(<コード> IFoo666 )のリストには作成できません。 List<IFoo>7 のリストは、<コード> IFoo18 sのリストとまったく異なるオブジェクトです。

 

Because a list of IFoos can contain some Bars as well, but a list of IFoos is not the same thing as a list of Bars.

Note that I used English above instead of using C#. I want to highlight that this is not a deep problem; you are just getting confused by the details of the syntax. To understand the answer you need to see beyond the syntax and think about what it actually means.

A list of IFoos can contain a Bar, because a Bar is an IFoo as well. Here we're talking about the elements of the list. The list is still a list of IFoos. We haven't changed that.

Now, the list you called foo is still a list of IFoos (more pedantically, foo is declared as a List<IFoo>). It cannot be anything else. In particular, it cannot be made into a list of Bars (List<Bar>). A list of Bar is a completely different object than a list of IFoos.

</div
 
 
1
 
vote

タイプ 998876619 のリストがある場合は、 IFoo1 を想定して IFoo0 を呼び出すことができます。 IFoo2 。ただし、 IFoo3 ではできませんので、 IFoo5 を使用できる IFoo4 を使用することはできません。しかし<コード> IFoo6 <コード> 998876627 は、<コード> IFoo8 を使用しているすべての場所でバーを使用することができます。 <コード> IFoo9

 

If you have a list of type List<IFoo> you can call list.add(new Baz()); assuming Baz implements IFoo. However you can't do that with a List<Bar>, so you can't use a List<Bar> everywhere you can use a List<IFoo>.

However since Bar implements IFoo, you can use a Bar everywhere you use IFoo, so passing a Bar to add works when it expects and IFoo.

</div
 
 
1
 
vote

私は変換を容易にするためにいくつかのlinqを使いました

<事前> <コード> Bar0

他の答えよりも少し少ない答えですが、うまく機能します

 

I used some linq to make the conversion easier

List<Bar> bar = new List<Bar>(); bar.add(new Bar());  List<IFoo> foo = bar.Select(x => (IFoo)x).ToList(); 

It is a little less versbose than other answers but works well

</div
 
 

関連する質問

12  C#の冗長性?  ( Redundancy in c ) 
次のスニペットを取ります: <事前> <コード> List<int> distances = new List<int>(); 言語デザイナーの冗長性はありましたか?もしそうなら、なぜ? ...

13  一般的な部分表示:一般クラスをモデルとして設定する方法は?  ( Generic partial view how to set a generic class as model ) 
ASP.NET MVCアプリケーションで一般的なグリッドビューを作成しようとしています。 いくつかのコードで説明しましょう: <事前> <コード> public interface ITrustGrid<T> { IPagedList<T> Elem...

76  特定のJava Generics Castsのタイプ安全警告の意味は何ですか?  ( What is the meaning of the type safety warning in certain java generics casts ) 
Java警告の意味は何ですか? 型安全:オブジェクトからリスト&lt;整数&gt;実際に消去されたタイプリストをチェックしています 次のコードのように、オブジェクトを一般的な情報を使ってタイプにキャストしようとすると、この警告が表示されます。 <事前>...

1  反射を介してインターフェースタイプのコンストラクタを取得するには、タイプをループするよりも優れたアプローチがありますか?  ( Getting the constructor of an interface type through reflection is there a bett ) 
汎用型: IDirectorySource<T> where T : IDirectoryEntry 。 IGroup 、<コード>、<コード>、<コード> IOrganizationalUnit >、<コード> IGroup8 。 次のことを書くことができ...

10  Javaで一般的な機能はどのように実装されていますか?  ( How is generic function implemented in java ) 
Javaでの次の一般的な関数を理解しています: <事前> <コード> public static <T> T f(T x) { Integer[] arr = new Integer[4]; T ret = (T) arr[2]; retu...

2  TypesScript:Type '{}'は 'pick <t、k>'を入力するために割り当てられません、JavaScript `Pick`関数を正しく入力しますか?  ( Typescript type is not assignable to type pickt k how do i type java ) 
pick と呼ばれる関数を入力したい、私はTyptionScriptが組み込まれている<コード> Pick<T, K> を知っています。 Mが立ち往生しています。 指定された文字列に基づいて、 pick のプロパティを与えられた <ListView Name...

21  基本クラス静的メソッドから派生クラスタイプを取得する  ( Get derived class type from a bases class static method ) 
基本クラスの静的メソッドから派生クラスのタイプを取得したいと思います。 これはどのように達成することができますか? ありがとう! <事前> <コード> class BaseClass { static void Ping () { Type t ...

2  JavaでCRTPにキャストする方法  ( How to cast to crtp in java ) 
私はいくつかの基本的な一般的な割り当てをするかなり簡単なケースを持っています: <事前> <コード> final Detail detail = field.getAnnotation(Detail.class); final String example =...

1  Tlist <T>のための一般的なFrealllを書く方法  ( How to write a generic freeall for tlistt ) 
一般的な<コード> TList<T> とリストの各要素を解放するFreall関数を書く最善の方法は何ですか? TList<T>.FreeAll は、一般的なタイプがレコードまたは文字列であるかどうかは意味がないため、存在しないことを理解しています。それにも...

4  汎用タイプARGS拡張クラスを指定しますか?  ( Generic type args which specificy the extending class ) 
インタフェースを実装するクラスを持ちたい、特別なサブクラスをパラメータとして指定します。 <事前> <コード> public abstract Task implements TaskStatus<Task> { TaskStatus<T> listene...




© 2022 cndgn.com All Rights Reserved. Q&Aハウス 全著作権所有