У меня есть следующие классы:

public class Column
{
    public String Name;
    public String Value;
}

public class ColumnList : List<Column> {}

Тогда я делаю:

var cols = (from c in othercolumnlist
            select new Column
            {
               Name = c.Name,
            }).ToList() as ColumnList;

Однако он возвращает null. Как я могу успешно добавить в свой список?

1
Ivan-Mark Debono 24 Мар 2014 в 18:15
Вам действительно нужно наследовать от List<T>?? вы также можете увидеть этот вопрос stackoverflow.com/questions/5376203/inherit-listt
 – 
Habib
24 Мар 2014 в 18:17
Зачем ToList из BCL вернуть экземпляр вашего пользовательского класса ColumnList (на что вы надеетесь, применяя оператор as)?
 – 
O. R. Mapper
24 Мар 2014 в 18:18

4 ответа

Лучший ответ

То, что вы пытаетесь сделать, эквивалентно этому:

Animal animal = new Animal();
Dog dog = animal as Dog;

Одно из возможных решений - предоставить конструктор, который принимает существующий список и вызывает базовый конструктор, например:

public class ColumnList : List<Column>
{
    public ColumnList(IEnumerable<Column> collection):
         base(collection)
    {
    }
}

А затем создайте свой ColumnList из существующей коллекции.

var collection = othercolumnlist.Select(c => new Column { Name = c.Name });

var columnList = new ColumnList(collection);

Вы также можете предоставить метод расширения, чтобы упростить это:

public static class ColumnListExtensions
{
    public static ToColumnList(this IEnumerable<Column> collection)
    {
        return new ColumnList(collection);
    }   
}

var cols = othercolumnlist.Select(c => new Column { Name = c.Name })
           .ToColumnList();
4
dcastro 24 Мар 2014 в 18:37

ColumnList - это List<Column>, но List<Column> не ColumnList. Рассмотрим классы Animal и Dog:

public class Animal
{
}

public class Dog: Animal
{
}

Вы пытаетесь относиться к любому животному как к собаке. Но не все животные - собаки. Может быть Cat или Kangaroo. Вот почему as ColumnList возвращает null.

Вместо этого вам нужно создать новый экземпляр ColumnList и добавить в него столбцы вручную:

var columnList = new ColumnList();
columnList.AddRange(othercolumnlist.Select(c => new Column { Name = c.Name }));

Если вам нужно делать это часто, вы можете добавить статический метод создания в свой класс ColumnList:

public static ColumnList CreateFrom(ColumnList other)
{
     var columnList = new ColumnList();
     columnList.AddRange(other.Select(c => new Column { Name = c.Name }));
     return columnList;
}

И используйте это так:

var columnList = ColumnList.CreateFrom(otherColumnList);
7
Sergey Berezovskiy 24 Мар 2014 в 18:31

То, что вы пытаетесь сделать, - это преобразовать List<Column> в ColumnList, что предполагает, что все List<T> являются ColumnList, а это, очевидно, не так.

Однако вы можете инициализировать новый экземпляр ColumnList, передав результат вашего запроса

new ColumnList().AddRange(othercolumnlist
    .Select(x => new Column { Name = x.Name })
    .ToList());
2
James 24 Мар 2014 в 18:53
Эм, ты не можешь подняться? Что вы можете. (object)"Hello world"
 – 
Lews Therin
24 Мар 2014 в 18:29
string происходит от object, поэтому ваш пример не повышает, а понижает (что совершенно законно). Повышение приведения будет происходить var obj = new object(); string str = (string)obj - и хотя это сработает, string - это особый тип объекта, и среда CLR обрабатывает его по-разному.
 – 
James
24 Мар 2014 в 18:40
1
Строка происходит от объекта, и я привожу строку к объекту. Это кастинг. Я создаю наследственную цепочку.
 – 
Lews Therin
24 Мар 2014 в 18:43
Ах, подождите - я полностью перепутал определения, приношу свои извинения.
 – 
James
24 Мар 2014 в 18:50

Вы могли бы, если бы вы определили конструктор копирования для вашего типа ColumnList:

public class ColumnList : List<Column>
{
    public ColumnList(IEnumerable<Column> src) : base(src)
    {
    }
}

И тогда вы делаете:

var cols = new ColumnList(from c in othercolumnlist
            select new Column
            {
               Name = c.Name,
            }).ToList());

Причина, по которой ToList() возвращает List, а не ColumnList. Это может быть только ColumnList, если вы явно создаете его как один, но никогда не наоборот.

0
dcastro 24 Мар 2014 в 18:26