无法将类型IEnumerable转换为List

17

我使用C#和Unity3d已经有几年了,但是现在刚开始学习.NET编程。我遇到了以下错误:

无法隐式转换类型 'System.Collections.Generic.IEnumerable<URL>' 到 'System.Collections.Generic.List<URL>'。 显式转换存在(是否缺少强制转换?)

这是我的代码:

namespace TestBrowserHistory
{
    public class Test1
    {
        public Test1()
        {

        }
          static void Main()
    {
        InternetExplorer myClass = new InternetExplorer();
        List<URL> calledList = myClass.GetHistory();
        Console.WriteLine("Hello!");
        Console.WriteLine(calledList[1]);
        Console.ReadLine();
    }
    }
}

public class InternetExplorer
{
    // List of URL objects
    public List<URL> URLs { get; set; }
    public IEnumerable<URL> GetHistory()
    {
        // Initiate main object
        UrlHistoryWrapperClass urlhistory = new UrlHistoryWrapperClass();

        // Enumerate URLs in History
        UrlHistoryWrapperClass.STATURLEnumerator enumerator =
                                           urlhistory.GetEnumerator();

        // Iterate through the enumeration
        while (enumerator.MoveNext())
        {
            // Obtain URL and Title
            string url = enumerator.Current.URL.Replace('\'', ' ');
            // In the title, eliminate single quotes to avoid confusion
            string title = string.IsNullOrEmpty(enumerator.Current.Title)
                      ? enumerator.Current.Title.Replace('\'', ' ') : "";

            // Create new entry
            URL U = new URL(url, title, "Internet Explorer");

            // Add entry to list
            URLs.Add(U);
        }

        // Optional
        enumerator.Reset();

        // Clear URL History
        urlhistory.ClearHistory();

        return URLs;
    }

}

感谢任何帮助!


嗨!也许你可以更具体一些:你在哪里遇到了这个错误?对于这样的编译错误,我们不需要你整个项目的源代码。 - Kek
可能是重复的问题:IEnumerable<T>转换为List<T> - dash
同时也重复在这里:https://dev59.com/CnNA5IYBdhLWcg3wcNbF将IEnumerable<T>转换为List<T>的最佳方法是使用ToList()方法。例如,假设有一个IEnumerable<T>变量myEnumerable,可以通过以下方式将其转换为List<T>:List<T> myList = myEnumerable.ToList(); - dash
8个回答

22
你之所以会遇到错误,是因为myClass.GetHistory();返回的是IEnumerable<URL>,它在编译时与List<URL>不同,虽然在运行时实际上是List<URL>。将方法签名更改为返回List<URL>,因为你已经这样做了。
public List<URL> GetHistory()

其他的解决方法是将方法调用结果转换为 List<URL>

List<URL> calledList = (List<URL>)myClass.GetHistory();

或者从结果构造新的列表

List<URL> calledList = new List<URL>(myClass.GetHistory());

如果您不需要列表功能,您可以将calledList定义为IEnumerable

var calledList = myClass.GetHistory();

16
你可以在可枚举对象上调用.ToList()方法。 - CMircea

3
您定义的GetHistory方法返回一个IEnumerable,而您将其赋值给了一个IList。要么更改定义,要么更改用法。
如果您不需要更改集合,我建议将GetHistory的定义更改为IEnumerable。

3

列表是可枚举的,但反过来则不成立。

如果您需要列表操作,应将方法更改为返回IList<>而不是IEnumerable。或者,您应该将返回值分配给一个IEnumerable变量而不是一个List。这将限制您只能使用IEnumerable方法(您可以使用foreach和使用LINQ的 .First 等内容,但不能按特定位置引用,例如)。这对于您最终需要的内容可能已经足够了。


你的第一句话就把一切都说清楚了。 - Everts

1

这里是错误

List<URL> calledList = myClass.GetHistory(); 

由于GetHistory方法返回IEnumerable<URL>

public IEnumerable<URL> GetHistory()

编辑:

解决方案:只需将GetHistory()方法的返回值更改为IList<T>


我没有给它点踩,但我猜测原因是重复创建新列表而不是重用现有列表。 - Branko Dimitrijevic
GetHistory 方法中,有一行代码 return URLs;,其中 URLs 的类型是 List<URL>。理论上,你可以将其强制转换回其实际运行时类型,而不必创建一个全新的列表。 - Branko Dimitrijevic
好的,我忽略了这一点,感谢你指出来,很有道理! - sll

1
与其他人所说的不同,您可以简单地采取以下措施:
GetHistory();
List<URL> calledList = URLs;

由于GetHistory在任何情况下都会修改URLs, 所以从它返回任何结果是没有多大意义的。此外,您可能需要考虑是否需要显式调用GetHistory - 或许相应的代码应该在第一次调用URLs getter时隐式执行?

另外,为什么不使用foreach


1
你可以使用 Linq lambda 提供的 tolist() 方法将 IEnumerable 转换为 List。
using System.Linq;

List<URL> calledList = myClass.GetHistory().ToList();

1
要让事情正常运作,您只需要将GetHistory()方法的返回类型更改为List<URL>
您可以将List强制转换为IEnumerable,但反过来不行。编译器被告知GetHistory返回IEnumerable,即使它实际上是一个列表,编译器也不知道这一点。

0

只需添加

yield return U;

结束 while 块并删除

 return URLs;

之后的函数是这样的

public IEnumerable<URL> GetHistory()
{
    // Initiate main object
    UrlHistoryWrapperClass urlhistory = new UrlHistoryWrapperClass();

    // Enumerate URLs in History
    UrlHistoryWrapperClass.STATURLEnumerator enumerator =
                                       urlhistory.GetEnumerator();

    // Iterate through the enumeration
    while (enumerator.MoveNext())
    {
        // Obtain URL and Title
        string url = enumerator.Current.URL.Replace('\'', ' ');
        // In the title, eliminate single quotes to avoid confusion
        string title = string.IsNullOrEmpty(enumerator.Current.Title)
                  ? enumerator.Current.Title.Replace('\'', ' ') : "";

        // Create new entry
        URL U = new URL(url, title, "Internet Explorer");

        // Add entry to list
        URLs.Add(U);
        yield return U;
    }

    // Optional
    enumerator.Reset();

    // Clear URL History
    urlhistory.ClearHistory();


}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接