简体   繁体   中英

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?

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

}

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

What about trying

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

ie, return directly Post instead of IData<Post> .

You should explicitly implement IData<Post>.Select and provide your own Select with the appropriate return value. For example:

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

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

However, if you do this:

IData<Post> post = new Post();
Post p = post.Select(1);

post.Select(1) still returns IData<Post> . See Femaref's answer on a refactoring of the interface to allow this.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM