IList‹IClient› метод‹T›(), где T : Iclient не может добавить клиентский объект в список

public IList GetClientsByListofID(IList id) где T : IClient {клиенты IList = new List(); клиенты.Добавить (новый клиент (3)); }

Я получаю ошибку компилятора здесь:

невозможно преобразовать Bailey.Objects.Client в T

Объект клиента реализует интерфейс IClient. Моя цель здесь - попытаться ослабить связь между моими классами (изучение DI-вещей atm). Я думал, что могу сказать, что он может использовать любой тип клиентского объекта, и это будет возвращено.

Я здесь совсем не в теме?

Спасибо

Джон Хокинс


person Jon    schedule 14.04.2009    source источник


Ответы (5)


Вы не можете использовать общие ограничения таким образом. Как компилятор может гарантировать, что параметр типа является Client просто потому, что он реализует интерфейс IClient? Разве многие типы не могут реализовать этот интерфейс?

В этом случае (то есть в случае, когда вам нужно работать с типом, а не с интерфейсом) лучше ограничивать параметр типа самим типом следующим образом:

public IList<T> GetClientsByListofID<T>(IList<int> ids) where T : Client
{
    IList<T> clients = new List<T>();
    clients.Add(new Client(3));
    // ...
}

и однажды сделав это, я задаюсь вопросом, нужен ли вам вообще общий метод:

public IList<Client> GetClientsByListofID(IList<int> ids)
{
    IList<Client> clients = new List<Client>();
    clients.Add(new Client(3));
    // ...
}
person Andrew Hare    schedule 14.04.2009
comment
Хорошая точка зрения. Другое решение состоит в том, чтобы метод возвращал IList‹IClient› вместо IList‹T›. - person Szymon Rozga; 14.04.2009
comment
может быть, я неправильно понимаю, но я думал, что если бы он реализовал этот интерфейс, его можно было бы вернуть как IClient и не беспокоиться о его фактическом классе. Я думаю, что я запутался и понял, что в этой проблеме дженерики не нужны (ваше второе решение работает отлично). Спасибо - person Jon; 14.04.2009
comment
к сожалению, это все равно приведет к ошибке компиляции. Это связано с тем, что объявление списка НЕ ​​соответствует оператору .Add в строке ниже. Вы не можете добавить конкретный тип в открытый типизированный список. Вот почему вы получаете ошибку компиляции. - person Joseph; 14.04.2009

Client is a IClient. T is a IClient.

Где вы указали, что T это Client? Нигде!

Я думаю, вам нужен IClientFactory или IClientRepository, который будет создавать/извлекать экземпляры IClient для вас. Затем вы сможете использовать различные реализации этой фабрики/репозитория.

person ybo    schedule 14.04.2009

Попробуй это:

public interface IClient
{
    string Name { get; }
}

public class Client : IClient
{
    public string Name { get; set; }
}

     ...

public IList<T> GetClientsByListofID<T>( IList<int> ids )
         where T : class, IClient
{
    var clients = new List<T>();
    var client = new Client { Name = "bob" } as T;

    clients.Add( client );

    return clients;
}

Применение:

     var clients = this.GetClientsByListOfID<Client>( null );
person tvanfosson    schedule 14.04.2009

Ваша проблема не в ограничении

where T : IClient

а скорее в использовании вашего списка.

Вы не можете сказать это:

IList<T> clients = new List<T>();
clients.Add( new Client(3));

вы МОЖЕТЕ сказать это: (это предполагает, что ваше ограничение включает «новое»)

IList<T> clients = new List<T>();
clients.Add( new T());

в этом случае ваше ограничение должно быть:

    where T : new(), IClient

или вы могли бы сделать это, но вообще не использовали бы дженерики:

IList<T> clients = new List<Client>();
clients.Add( new Client(3));

Причина, по которой вы не можете сделать то, что пытаетесь сделать, заключается в том, что компилятор не может гарантировать, что тип T будет иметь тип Client, поэтому он выдает вам ошибку компилятора. На самом деле это не имеет ничего общего с вашим ограничением.

person Joseph    schedule 14.04.2009

То, что вы делаете, не работает, потому что в дженериках С# 3.0 не поддерживается ковариация.

Вы можете сделать что-то вроде этого:

    interface IClient
    {
        int Id { get; set; }
    }

    class Client : IClient
    {
        public int Id { get; set; }
        public Client() { }
    }

    // ...

    public IList<T> GetClientsByListofID<T>(IList<int> ids) where T : IClient, new()
    {
        IList<T> clients = new List<T>();
        clients.Add(new T() { Id = 3 });
        // ...
        return clients;
    }

... но мне интересно, нужны ли вам вообще дженерики.

person bruno conde    schedule 14.04.2009