如何将“类列表”转换为“其接口列表”?

时间:2019-05-09 11:43:27

标签: c# class interface

我需要将一个类列表转换为它自己的接口列表。

所以我有接口Demo_Interface和两个基于Demo_Interface的类, 现在,我创建类似List<Test_Class1>

的类的列表

我有一个带有List<Demo_Interface>参数的函数。

此处的界面:

       interface Demo_Interface
        {
            int test_int { get; set; }
        }

以下是整个代码:

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);
            }
        }
    }
}

Test_Class1 使用 Demo_Interface 时,如何将List<Test_Class1>投射到List<Demo_Interface>

3 个答案:

答案 0 :(得分:2)

您可以尝试

List<Test_Class1> testDemo = new List<Test_Class1>(); //list of Test_Class1 instances
List<Demo_Interface> result = testDemo.ToList<Demo_Interface>();

这是安全的,因为我们没有直接将testDemo强制转换为其接口。我们保持testDemo不变,并创建result的列表Demo_Interface

答案 1 :(得分:2)

如果您只需要像示例中所示的那样通过List<Demo_Interface>进行枚举,则不必进行任何类型的显式转换。 List<T>实现IEnumerable<T>,这是covariant通用类型。

  

集合的协方差可以将更多派生类型的集合隐式转换为更少派生类型的集合

在您的情况下,List<Test_Class1>实现了IEnumerable<Test_Class1>,但是由于Test_Class1实现了Demo_Interface,因此您可以利用泛型方差并编写例如以下内容:

IEnumerable<Test_Class1> col = new List<Test_Class1>();
IEnumerable<Demo_Interface> colImplicit = col;

这基本上意味着您的Output_Class方法可以接受IEnumerable<Demo_Interface>参数,并且您可以传递两个列表,而无需使用Cast<T>显式转换它们或使用{{ 1}}。

ToList<T>

答案 2 :(得分:1)

您不能将List<ClassThatImplementsInterface>转换为List<IInterfaceItImplements>

如果可以的话,您做到了:

var classList = new List<ClassThatImplementsInterface>();
var interfaceList = (List<IInterfaceItImplements>)classList;

...那么您就可以做到这一点:

interfaceList.Add(new SomeOtherClassThatImplementsTheInterface);

但是投射列表不会创建新列表。在上面的示例中,没有两个列表。有两个引用相同列表的变量。如果可以如上所示进行转换,则可以定义一种类型的列表,并为其添加完全不同的类型。编译器可以防止这种情况。

您可以

  • 创建一个新的List<IDemoInterface>并将项目添加到其中。 (或数组,IEnumerable等)
  • 按原样保留列表,并在需要时仅投射单个项目。在大多数情况下,我们不需要将某些内容强制转换为它实现的接口。

如果我们需要将整个集合强制转换为其他类型,则可能是因为我们将其作为参数传递。

这实际上是一个很好的理由,不是将方法参数定义为像List<T>这样的集合类型,可以修改它,除非我们有意修改集合。

这就是为什么我们传递不太具体的集合类型(例如IEnumerable<T>)的原因之一。

假设方法参数看起来像这样:

void MethodINeedToPassTheArgumentTo(IEnumerable<IDemoInterface> items)

现在我们可以拿起List<TestClass>来做到这一点:

MethodINeedToPassTheArgumentTo(testClassList.Cast<IDemoInterface>);

我们没有创建新的收藏集。我们正在传递一个引用,该引用允许其他方法查看列表中的项目,每个单独都强制转换为IDemoInterface。出于实际目的,它像其他IDemoInterface一样将查找到其他方法中,这是可以的,因为其他项无法修改该集合。它无法尝试将其他类型添加到List<TestClass>中。