dagatsoin
dagatsoin

Reputation: 2656

How to write an interface for a generic method

I have the class PlayersCollection and I want to interface it in IWorldCollection. The probleme is about writing the declaration in the interface which cause me this error :

Assets/Scripts/Arcane/api/Collections/ItemsCollection.cs(17,22): error CS0425:
The constraints for type parameter `T' of method
`Arcane.api.ItemsCollection.Get<T>(int)
must match the constraints for type parameter `T' of
interface method `Arcane.api.IWorldCollection.Get<T>(int)'.
Consider using an explicit interface implementation instead

Here is my class and my interface. How to write a generic method implementation with a class constraint ?

public class PlayersCollection : IWorldCollection
{

    public Dictionary<Type, object> Collection;

    public PlayersCollection()
    {
        Collection = new Dictionary<Type, object>();
    }

    public T Get<T>(int id) where T: PlayerModel
    {
       var t = typeof(T);
       if (!Collection.ContainsKey(t)) return null;
       var dict = Collection[t] as Dictionary<int, T>;
       if (!dict.ContainsKey(id)) return null;
       return (T)dict[id];
    }
  }
}


public interface IWorldCollection
{
    T Get<T>(int id) where T : class;// Work when I change "class" to "PlayerModel".
}

Big thanks for your help :)

Upvotes: 2

Views: 988

Answers (3)

Pieter Geerkens
Pieter Geerkens

Reputation: 11883

It seems to me that the following will meet the requirements, by pushing the generic type parameter up to the class/interface level:

public class PlayersCollection<T> : IWorldCollection<T> where T : PlayerModel
{

    public Dictionary<Type, T> Collection;

    public PlayersCollection()
    {
        Collection = new Dictionary<Type, T>();
    }

    public T Get(int id)
    {
       var t = typeof(T);
       if (!Collection.ContainsKey(t)) return null;
       var dict = Collection[t] as Dictionary<int, T>;
       if (!dict.ContainsKey(id)) return null;
       return (T)dict[id];
    }
  }

public interface IWorldCollection<T> where T : class
{
    T Get(int id);
}

If I have missed something in the requirements, please let me know.

Upvotes: 1

Nadia Chibrikova
Nadia Chibrikova

Reputation: 5036

I'm not sure why you need this interface, but maybe this will help:

public class PlayersCollection<T> : IWorldCollection<T> where T:PlayerModel
{

public Dictionary<Type, object> Collection;

public PlayersCollection()
{
    Collection = new Dictionary<Type, object>();
}

public T Get(int id)
{
    ...
}
}



public interface IWorldCollection<T> where T:class
{
    T Get(int id);
}

Upvotes: 1

VMAtm
VMAtm

Reputation: 28345

Try this:

public class PlayersCollection : IWorldCollection<PlayerModel>
{

    public Dictionary<Type, object> Collection;

    public PlayersCollection()
    {
        Collection = new Dictionary<Type, object>();
    }

    public PlayerModel Get<PlayerModel>(int id)
    {
        ///
    }
  }
}


public interface IWorldCollection<T>
{
    T Get<T>(int id);
}

In your case, in the class implementing your interface, you adding more condition for your class:

  • where T : class in the interface
  • where T: PlayerModel in the class

If, for some reason, you need to add a constraint into your interface, you need to add an interface or base class, which will be placed to the interface declaration, and you'll have to derive from it in your PlayerModel class, like this:

public abstract class Model
{
}

public class PlayerModel : Model
{
}

public interface IWorldCollection<T> where T : Model
{
    T Get<T>(int id);
}

public class PlayersCollection : IWorldCollection<PlayerModel>
{
    ///

    public PlayerModel Get<PlayerModel>(int id)
    {
        ///
    }
  }
}

Upvotes: 0

Related Questions