Question

I want to be able to use Linq's '.where' statement with my class 'Books' (a list of 'Book') that implements interface IEnumerable.

//THE PROBLEM IS HERE.
IEnumerable list3 = bookList.Where(n => n.author.Length >= 14);

And I get the following error:

Error 1 'Assignment2CuttingPhilip.Books' does not contain a definition for 'Where' and no extension method 'Where' accepting a first argument of type 'Assignment2CuttingPhilip.Books' could be found (are you missing a using directive or an assembly reference?) C:\Users\Alex\Dropbox\cos570 CSharp\Assignment2CuttingPhilip\Assignment2CuttingPhilip\Assignement2PhilipCutting.cs 132 33 Assignment2CuttingPhilip

My Code is as follows:

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;


namespace Assignment2CuttingPhilip
{
    public class Book 
    {
        public string title;
        public string author;

        public Book(string title, string author) {
            this.title = title;
            this.author = author;
        }

        public override string  ToString()
        {  return "Title:\'" + title + "\', Author:" + author;  }

    }

    public class Books : IEnumerable
    {
        private Book[] _books;
        public Books(Book[] bArray){
            _books = new Book[bArray.Length];
            for (int i = 0; i < bArray.Length; i++)
            {_books[i] = bArray[i];}
        }

        IEnumerator IEnumerable.GetEnumerator()
        {return (IEnumerator) GetEnumerator();}

        public BooksEnum GetEnumerator()
        {return new BooksEnum(_books);}

    }

    public class BooksEnum : IEnumerator{
        public Book[] _books;
        int position = -1;

        public BooksEnum(Book[] list){
            _books = list;}

        public bool MoveNext()
        {
            position++;
            return (position < _books.Length);
        }

        public void Reset()
        {position = -1;}

        object IEnumerator.Current
        { get { return Current; }}

        public Book Current
        {{ try
                { return _books[position];}
                catch (IndexOutOfRangeException)
                {throw new InvalidOperationException();}
        }}
    }

    class Assignement2PhilipCutting
    {
        static void Main(string[] args)
        {
            Book[] bookArray = new Book[3] 
            {
                new Book("Advance C# super stars",  "Prof Suad Alagic"),
                new Book("Finding the right lint",  "Philip Cutting"),
                new Book("Cat in the hat",          "Dr Sues")
            };

            Books bookList = new Books(bookArray);

            IEnumerable List = from Book abook in bookList  
                               where abook.author.Length <= 14
                               select abook;

            IEnumerable list2 = bookArray.Where(n => n.author.Length >= 14);

            //**THE PROBLEM IS HERE**.
            IEnumerable list3 = bookList.Where(n => n.author.Length >= 14);

            foreach (Book abook in List)
            { Console.WriteLine(abook); }
        }
    }
}

It should be pretty straight forward do this, but why cant I use my Enumerable Books list with Linq in C#? Shouldn't I be able to make an enumerable list that I can query with Fluent Linq commands?

Thanks Phil

Was it helpful?

Solution

Your Books class must implement IEnumerable<Book>, not just IEnumerable. The Where extension, as most of LINQ extensions, are made for objects implementing IEnumerable<T>. This interface is located in the System.Collections.Generic namespace.

Right now you could use the Cast() extension:

var list3 = bookList.Cast<Book>().Where(n => n.author.Length >= 14);

This is something you can do with legacy collections that only implements IEnumerable. However, in your scenario, the Books class is yours so I really would recommend that you make it implement IEnumerable<Book>.

OTHER TIPS

You need to implement IEnumerable<T> (generic one) rather than just IEnumerable, and you'll be able to use LINQ-related extension methods.

You should either implement IEnumerable<T> and not just IEnumerable or call Cast<Book> as below

IEnumerable list3 = bookList.Cast<Book>.Where(n => n.author.Length >= 14);

I would suggest to use the first approach since you have the ability but when you can't change the implementation of your list you can use the Cast<T> to convert from non generic enumerable to a generic enumerable. However pay attention to the fact that Cast<T> will only cast not convert, so any custom cast operators will result in an exception

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top