Question

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

I am getting a compiler error here:

cannot convert from 'Bailey.Objects.Client' to 'T'

The client object implements the IClient interface. My goal here is to try and loosen the coupling between my classes (learning DI stuff atm). I was thinking that I can say it can use any type of client object and that would be returned.

Am I completely off base here?

Thanks

Jon Hawkins

Was it helpful?

Solution

You cannot use generic constraints in this way. How can the compiler guarantee that the type parameter is a Client simply because it implements the IClient interface? Couldn't many types implement that interface?

In this case (that is in the case where you need to work with the type, not the interface) it is better to constrain the type parameter with the type itself like this:

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

and once doing that I am wondering if you need a generic method at all:

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

OTHER TIPS

Client is a IClient. T is a IClient.

Where did you specify that T is a Client? Nowhere!

I think you need a IClientFactory or IClientRepository that will create/retrieve IClient instances for you. You will then be able to use different implementations of this factory/repository.

Try this:

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

Usage:

     var clients = this.GetClientsByListOfID<Client>( null );

Your problem is not in the constraint

where T : IClient

but rather in the use of your List.

You can't say this:

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

you CAN say this: (this assumes your constraint includes "new")

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

in this case your constraint would then need to be:

    where T : new(), IClient

or you could do this but it wouldn't use generics at all:

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

The reason why you can't do what you're trying to do is because the compiler can't gaurantee that the type T will be of type Client, which is why it's giving you the compiler error. It doesn't have anything to do with your constraint really.

What your are doing doesn't work because in C# 3.0 generics don't support covariance.

You could do something like this:

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

... but I wonder if you need generics at all.

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