如果方法返回接口类型,为什么我不能将结果传递给具体类型?

时间:2012-09-06 13:40:30

标签: c# interface concrete

这个问题可能有点令人困惑,但很难在主题标题中明确这个问题。

我声明并实现了这样的方法:

public IList<string> GetBookTitles()
{
    IList<string> bookTitles = new List<string>();
    // do something to populate the bookTitles list.
    return bookTitles;
}

为什么我不能将此方法的结果传递给List<string>?毕竟,List<string>是一种IList<string>

5 个答案:

答案 0 :(得分:2)

嗯,对于初学者,只需查看IList的成员并将其与List进行比较。 List具有IList没有的方法。 (List有一个BinarySearch方法IList没有,只是作为一个例子。)

例如,数组也实现了IList。但是,数组不是List,因此您不能也不应该将string[]传递给接受List<string>的方法。

您有一些可能的解决方案。一种方法是改变你的方法以返回List<string>而不是IList<string>(这就是我的建议)。如果这是您真正需要的,那么您不应该将返回类型限制为IList<string>。另一个(较差的)选项是在将结果传递给下一个方法之前将结果转换回List<string>,因为你碰巧知道底层类型确实是什么。

答案 1 :(得分:1)

  

毕竟,List<string>是一种IList<string>

但还有其他种类的IList<String>

如果您的方法要返回IList<String>而不是ReadOnlyCollection<String>,该怎么办?

IList<string> x = new ReadOnlyCollection<string>();
List<string> y = x;  //Huh?

答案 2 :(得分:1)

编译器在决定是否可以将GetBookTitles的结果赋值给变量时使用方法的签名而不是实现,因此它无法知道结果实际上是List。如果它允许你做这样的事情,那么你可以这样写:

List<string> myBooks = GetBookTitles();
myBooks.Sort();

在您的示例中,您可以执行此操作,事实上,如果您投射方法的结果,则可以执行此操作:

List<string> myBooks = (List<string>)GetBookTitles();

但是有一天你可以决定你的图书集是不可修改的,你可以按如下方式重写你的方法:

public IList<string> GetBookTitles()
    {
        IList<string> tmp = new List<string>();
        // do something to populate the bookTitles list.
        IList<string> bookTitles = new ReadOnlyCollection<string>(tmp);
        return bookTitles;
    }

ReadOnlyCollection没有实现Sort,所以你的应用程序会编译,但会在运行时崩溃。 使用强制转换方法会在尝试执行转换时崩溃,但在这种情况下,您负责决定这种转换是否可行并且没有编译器试图猜测。

更好的方法可能是使用as而不是cast和chek for null。即:

List<string> myBooks = GetBookTitles() as List<string>;
if (myBooks != null)
    myBooks.Sort();

答案 3 :(得分:0)

你应该可以,你只需要一个明确的转换。

List<string> foo = (List<string>)GetBookTitles()

应该这样做。

答案 4 :(得分:0)

接口可以在不同的类中实现。因此,很难找到相应的班级。

您可以在IList中输入强制转换为List !!!