Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Interface method return type to be class that implements the interface

I'm having trouble getting my head around interfaces. After trawling through similar questions on here, I've come up with the following interface, for defining the CRUD operations required for all my classes:

public interface IData<T>
{
    IData<T> Select(int id);
    List<T> SelectMultiple();
    void Insert();
    void Update();
    void Delete();
}

This is then implemented within my partial classes:

public partial class Post : IData<Post>
{
    public IData<Post> Select(int id)
    {
        MyDataContext dc = MyDataContext.Create();
        return dc.Posts.Single(p => p.PostID == id);
    }

    public List<Post> SelectMultiple()
    {
        MyDataContext dc = MyDataContext.Create();
        return dc.Posts.ToList();
    }

    // Update() and Delete() declarations
}

This all compiles fine, however if I try to use the Post Select() method:

Post p = new Post().Select(1);

It fails with Cannot implicitly convert type 'IData' to 'Post'. An explicit conversion exists (are you missing a cast?)

Which makes sense, but how do I have it so that it doesn't require a Cast? I want the Select to return a Post (but not define Post as the return type at the interface level). Have I misunderstood interfaces, or is there a quick alteration I can make?

like image 305
Lazlow Avatar asked Nov 28 '10 16:11

Lazlow


2 Answers

You need to change the methods to return Post instances, then add explicit interface implementations that return the interface.

For example:

public partial class Post : IData<Post> {
    Post Select(int id) { ... }
    IData<Post> IData<Post>.Select(int id) { return Select(id); }
}
like image 37
SLaks Avatar answered Sep 20 '22 19:09

SLaks


You want to return something of type T, not IData<T>, so just change the signature (at least I guess this is what you want, as you'd return List<IData<T>> otherwise):

public interface IData<T>
{
  T Select(int id);
  List<T> SelectMultiple();
  void Insert();
  void Update();
  void Delete();
}

and implement it appropiately:

public Post Select(int id)
{
    MyDataContext dc = MyDataContext.Create();
    return dc.Posts.Single(p => p.PostID == id);
}

If you just want this behaviour in the Post class, explicitly implement the IData<T> interface:

public partial class Post : IData<Post>
{
  public Post Select(int id)
  {
      MyDataContext dc = MyDataContext.Create();
      return dc.Posts.Single(p => p.PostID == id);
  }

  IData<Post> IData<Post>.Select(int id)
  {
      return Select(id);
  }

}
like image 134
Femaref Avatar answered Sep 20 '22 19:09

Femaref