views:

524

answers:

5

Hi all,

public IList<T> GetClientsByListofID<T>(IList<int> ids) where T : IClient
{
    IList<T> clients = new List<T>();
    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

+5  A: 

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));
    // ...
}
Andrew Hare
Good point. Another solution would be to have the method return IList<IClient> instead of IList<T>.
siz
maybe I am misunderstanding but I thought that if it did implement that interface it could be returned as an IClient and not worry about its actual class. I think I got my knickers in a twist and realized that in this problem generics was not needed, (ur second solution works perfectly). Thank you
Jon
The problem here is not the constraint...
bruno conde
this would still result in a compile error, unfortunately. This is due to the way the declaration of the List does NOT match the .Add statement on the line below. You can't add a concrete type to an open typed list. That's why you're getting the compile error.
Joseph
+1  A: 

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.

ybo
+1  A: 

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 );
tvanfosson
A: 

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.

bruno conde
+1  A: 

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.

Joseph