C#中的转换问题

Nir*_*bey 0 c# oop

我有一个程序

using System;
using System.Collections.Generic;

namespace Generic
{
    public class Program
    {
        public static void Main()
        {
            List<string> dd= Program.get();
        }

        public static IList<string> get()
        {
            List<string> str = new List<string>();
            return str;  
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

在执行上面我得到:

无法隐式转换 'System.Collections.Generic.IList<string>'
'System.Collections.Generic.List<string>'.存在显式转换(您是否错过了演员?).

既然,List派生IList,这不应该失败.那么为什么C#会抛出这个错误呢?

Sam*_*Sam 6

虽然您可以保证所有List对象都是类型IList,但您无法保证所有IList对象都是类型List,因为它可能是实现接口的完全不同的类.这意味着在线

List<string> dd= Program.get();
Run Code Online (Sandbox Code Playgroud)

你试图告诉编译器它IList实际上是一个List,但它不知道.该IList实际上可以从不同的子类,甚至是不相关的衍生List.你可以做一个明确的演员,

List<string> dd= (List<string>)Program.get();
Run Code Online (Sandbox Code Playgroud)

但如果有可能Program.get()返回实际发生的其他内容List,这可能会导致运行时问题IList.

最好显式地声明返回类型,get()List<string>好像你真的需要访问仅可用的功能一样List,或者只是声明类型,ddIList<string>好像IList接口提供了你打算调用的所有方法一样.

例如,请考虑以下事项:

interface Foo {
    public void doSomething();
}

class Bar : Foo {
    public override void doSomething() {
        Console.WriteLine("Hello World!");
    }
}

class Baz : Foo {
    public override void doSomething() { 
        Console.WriteLine("Goodbye World!");
    }
}

class Program {
    public static void Main(string[] args) {
        Foo myFoo = getMyFoo();
        myFoo.doSomething();
    }

    static Random random = new Random();
    static Foo getMyFoo() {
        if (random.NextDouble() < 0.5){
            return new Bar();
        }
        else {
            return new Baz();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我们可以看到,无论BarBaz有型的Foo,但我们永远不会保证其类型会从返回getMyFoo(),只知道它是类型Foo.我们可以尝试显式地转换myFoo为一个或另一个,但我们通常会在运行时失败,因为Baz它不是类型Bar,反之亦然.