简体   繁体   中英

Cannot convert type IEnumerable to List

I have been using C# with Unity3d for a few years now, but am just starting with .NET programming. I get the error:

Cannot implicitly convert type ' System.Collections.Generic.IEnumerable<URL> ' to ' System.Collections.Generic.List<URL> '. An explicit conversion exists (are you missing a cast?)

Here is my code:

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

}

Thanks for any help!

You get that error because myClass.GetHistory(); returns IEnumerable<URL> , which is not same as List<URL> at compile time, although it is actually List<URL> at runtime. Change method signature to return List<URL> , cause you already do that

public List<URL> GetHistory()

Other workarounds would be to cast method call result to List<URL>

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

Or construct new list from result

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

If you do not need List functionality, you could define calledList as IEnumerable

var calledList = myClass.GetHistory();

Your definition of the GetHistory methods returns an IEnumerable, and you are assigning it to an IList. Either change the definition , or the usage.

If you don't need to change the collection I would change the definition of GetHistory to IEnumerable.

A List is IEnumerable, but the reverse is not true.

If you need list operations, you should change your method to return an IList<> instead of IEnumerable. Alternately, you should assign the return value to an IEnumerable variable instead of a List. This will limit you to (without further manipulation) the IEnumerable methods (you can do a foreach and use LINQ things like .First, but you can't reference by specific position, for example). Which might be enough for what you ultimately need it for.

Here is the error

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

Since GetHistory method returns IEnumerable<URL>

public IEnumerable<URL> GetHistory()

EDIT:

Solution : just change the return value of GetHistory() method to IList<T>

To get things working you just need to change the return type of your GetHistory() method to List<URL> .

You can typecast a List to an IEnumerable, but not the other way around. The compiler is told that GetHistory returns IEnumerable, and even though it is a list, it doesn't know that.

In alternative to what others have said, you could simply:

GetHistory();
List<URL> calledList = URLs;

Since GetHistory modifies the URLs as its side-effect anyway, there is little purpose of returning any result from it. In addition to that, you might consider whether GetHistory needs to be explicitly called at all - perhaps the equivalent code should be implicitly executed when the URLs getter is first called?

Also, why aren't you using foreach ?

just add

yield return U;

end of while block and remove

 return URLs;

after that function is like this

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


}

You can just use tolist() provided by Linq lamda to convert from IEnumerable to List.

using System.Linq;

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM