[英]How to cast a 'list of classes' to a 'list of its interface'?
I need to cast a class list to its own interface list. 我需要将一个类列表转换为它自己的接口列表。
So I have interface Demo_Interface
and two classes based on Demo_Interface
, Now I create list of classes like List<Test_Class1>
所以我有接口
Demo_Interface
和两个基于Demo_Interface
类,现在我创建类列表,如List<Test_Class1>
And I have a function with List<Demo_Interface>
parameter. 我有一个带有
List<Demo_Interface>
参数的函数。
Here's interface : 这是界面:
interface Demo_Interface
{
int test_int { get; set; }
}
Here's Entire Code : 这是整个代码:
using System;
using System.Collections.Generic;
namespace ConsoleApp3
{
class Program
{
///// Main Interface
interface Demo_Interface
{
int test_int { get; set; }
}
//// Class 1 Based On Demo_Interface
class Test_Class1 : Demo_Interface
{
public int test_int { get; set; }
public string test_string { get; set; }
}
///// Class 2 Based On Demo_Interface
class Test_Class2 : Demo_Interface
{
public int test_int { get; set; }
public string test_string { get; set; }
}
//// And Main Class
class Main_Class
{
public List<Test_Class1> class_list_1 { get; set; }
public List<Test_Class2> class_list_2 { get; set; }
public Main_Class()
{
class_list_1 = new List<Test_Class1>() { };
class_list_2 = new List<Test_Class2>() { };
}
}
//// Console Main
static void Main(string[] args)
{
var new_main_class = new Main_Class();
Output_Class(new_main_class.class_list_1); ///// ==> ERROR
Console.ReadKey();
}
//// Simple Function for do something with interface
static void Output_Class(List<Demo_Interface> inter_input)
{
for (int i = 0; i < inter_input.Count; i++)
{
Console.WriteLine("{0} - {1}",i, inter_input[i].test_int);
}
}
}
}
How Can I cast List<Test_Class1>
to List<Demo_Interface>
, When Test_Class1 uses Demo_Interface ? 当Test_Class1使用Demo_Interface时 ,如何将
List<Test_Class1>
为List<Demo_Interface>
?
You can try 你可以试试
List<Test_Class1> testDemo = new List<Test_Class1>(); //list of Test_Class1 instances
List<Demo_Interface> result = testDemo.ToList<Demo_Interface>();
This is safe because we are not directly casting testDemo to its interface. 这是安全的,因为我们没有直接将testDemo强制转换为其接口。 We are keeping testDemo as it is and we are creating
result
which is list of Demo_Interface
我们保持testDemo,因为它是和我们正在创造
result
是列表Demo_Interface
If you need only to enumerate through the List<Demo_Interface>
like shown in example, you don't have to do any kind of explicit casting. 如果仅需要像示例中所示通过
List<Demo_Interface>
进行枚举,则不必进行任何类型的显式转换。 List<T>
implements IEnumerable<T>
which is covariant generic type. List<T>
实现IEnumerable<T>
,它是协变泛型类型。
Covariance for collections enables implicit conversion of a collection of a more derived type to a collection of a less derived type
集合的协方差允许将派生度更高的类型的集合隐式转换为派生度较小的类型的集合
In your case, List<Test_Class1>
implements IEnumerable<Test_Class1>
, but since Test_Class1
implements Demo_Interface
, you can take advantage of generics variance and write, for example, something like this: 在您的情况下,
List<Test_Class1>
实现IEnumerable<Test_Class1>
,但是由于Test_Class1
实现Demo_Interface
,您可以利用泛型方差并编写例如以下内容:
IEnumerable<Test_Class1> col = new List<Test_Class1>();
IEnumerable<Demo_Interface> colImplicit = col;
That basically means that your Output_Class
method can take IEnumerable<Demo_Interface>
argument and you'll be able to pass both lists without casting them explicitly using Cast<T>
or creating a new collection using ToList<T>
. 基本上,这意味着您的
Output_Class
方法可以使用IEnumerable<Demo_Interface>
参数,并且您可以传递两个列表,而无需使用Cast<T>
显式地转换它们或使用ToList<T>
创建新的集合。
private void Output_Class(IEnumerable<Demo_Interface> inter_input)
{
// do your thing
}
// Method invocation
Output_Class(new_main_class.class_list_1);
You cannot cast a List<ClassThatImplementsInterface>
as a List<IInterfaceItImplements>
. 您不能将
List<ClassThatImplementsInterface>
为List<IInterfaceItImplements>
。
If you could, and you did this: 如果可以,并且您这样做:
var classList = new List<ClassThatImplementsInterface>();
var interfaceList = (List<IInterfaceItImplements>)classList;
... then you would be able to do this: ...那么您将能够执行此操作:
interfaceList.Add(new SomeOtherClassThatImplementsTheInterface);
But casting the list doesn't create a new list. 但是投射列表不会创建新列表。 In the above example there aren't two lists.
在上面的示例中,没有两个列表。 There are two variables with references to the same list.
有两个引用相同列表的变量。 If you could cast as seen above, you would be able to define a list of one type and add a completely different type to it.
如果可以如上所示进行转换,则可以定义一种类型的列表,并为其添加完全不同的类型。 The compiler prevents that.
编译器可以防止这种情况。
You could 你可以
List<IDemoInterface>
and add the items to it. List<IDemoInterface>
并将项目添加到其中。 (Or an array, IEnumerable, etc.) If we need to cast a whole collection as a different type, it's likely because we're passing it as an argument. 如果我们需要将整个集合强制转换为其他类型,则可能是因为我们将其作为参数传递。
That's actually a good reason not to define a method argument as a collection type like a List<T>
which can be modified unless it's our intent to modify the collection. 实际上,这是一个很好的理由, 不要将方法参数定义为像
List<T>
这样的集合类型,可以修改它,除非我们打算修改集合。
That's one reason why we pass less-specific collection types, like IEnumerable<T>
. 这就是为什么我们传递不太具体的集合类型(如
IEnumerable<T>
。
Suppose the method argument looks like this: 假设方法参数看起来像这样:
void MethodINeedToPassTheArgumentTo(IEnumerable<IDemoInterface> items)
Now we can take our List<TestClass>
and do this: 现在我们可以使用
List<TestClass>
并执行以下操作:
MethodINeedToPassTheArgumentTo(testClassList.Cast<IDemoInterface>);
We're not creating a new collection. 我们不会创建新集合。 We're passing a reference that allows the other method to view the items in the list, each individually cast as
IDemoInterface
. 我们正在传递一个引用,该引用允许其他方法查看列表中的项目,每个项目分别转换为
IDemoInterface
。 For practical purposes it looks to the other method like a collection of IDemoInterface
, and that's okay because the other item can't modify the collection. 出于实际目的,它看起来像
IDemoInterface
的集合之类的另一种方法,这是可以的,因为另一项不能修改该集合。 It can't attempt to add other types into the List<TestClass>
. 它不能尝试将其他类型添加到
List<TestClass>
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.