Lee
Lee

Reputation: 3969

C# interfaces and generics

I'm confused as to how generics, namely T works in C#. It doesn't seem to behave the same way as C++, unless I'm mistaken. I'm trying to create a simple interface for a data gateway:

EDIT Updated to match the answers. Visual Studio now complains the derived classes don't implement the interface methods.

public interface IDataGateway<T>
{
    void InsertRow(T row);
    void UpdateRow(T row);
    IEnumerable<T> GetTable();
}

public class LibraryGateway : IDataGateway<Media>
{
    public void InsertRow(Media item) { }
    public void Updaterow(Media item) { }
    public IEnumerable<Media> GetTable() { }
}

I do not know what type will be passed, which is why I'm trying to use generics.

Upvotes: 1

Views: 246

Answers (7)

3dd
3dd

Reputation: 2540

You miss spelled Updaterow, it should read UpdateRow.

Easiets way to implement interface is to, click on interface name with mouse, hit ctrl+. and then select implement interface

Upvotes: 0

Jeremy Todd
Jeremy Todd

Reputation: 3289

From your examples, I think what would work best is making the interface itself generic, as opposed to the methods within it:

public interface IDataGateway<T>
{
  void InsertRow(T row);
  void UpdateRow(T row);
  IEnumerable<T> GetTable(T table); // ???
}

I think your GetTable() method also needs fixing -- if T is the type of the object contained in the table, then it (probably!) isn't also the type of the table. Maybe you just mean IEnumerable<T> GetTable();?

Then you could do:

public class LibraryGateway : IDataGateway<Media>
{
  public void InsertRow(Media item) { }
  public void UpdateRow(Media item) { }
  public IEnumerable<Media> GetTable() { }
}

...and I think that should do what you're looking for.

Upvotes: 1

Andreas Johansson
Andreas Johansson

Reputation: 172

Like this perhaps?

public interface IDataGateway<T>
{
    void InsertRow(T row);
    void UpdateRow(T row);
    IEnumerable<T> GetTable(T table);
}

public abstract class LibraryGateway<T>
{
    public void InsertRow(T item) { }
    public void Updaterow(T item) { }
    public IEnumerable<T> GetTable<T>() { }
}

public class MediaLibraryGateway : GateWay<Media>, IDataGateway<Media>
{

}

Upvotes: 0

Sam Harwell
Sam Harwell

Reputation: 100019

It looks like you are trying to create and implement a generic interface, not generic methods.

public interface IDataGateway<T>
{
    void InsertRow(T row);
    void UpdateRow(T row);
    IEnumerable<T> GetTable(T table);
}

public class LibraryGateway : IDataGateway<Media>
{
    public void InsertRow(Media item) { }
    public void Updaterow(Media item) { }
    public IEnumerable<Media> GetTable(Media table) { }
}

When you have a generic method (as in the original question), it means a single implementation (e.g. LibraryGateway.InsertRow) could get called with an argument of any type - known only at runtime. However, when you implement a generic interface, you can parameterize the interface so LibraryGateway.InsertRow operates specifically on items of type Media. Other implementations of IDataGateway<T> may operate on other types, but LibraryGateway only operates on Media objects.

Upvotes: 1

Guvante
Guvante

Reputation: 19221

You are defining a non-generic interface with three generic methods.

Each of these methods has the ability to accept any type T, as the value of T is not the same between them.

What you probably meant to do was define a generic interface with three non-generic methods.

public interface IDataGateway<T>
{
    void InsertRow(T row);
    void UpdateRow(T row);
    IEnumerable<T> GetTable(T table);
}

Upvotes: 0

MarcinJuraszek
MarcinJuraszek

Reputation: 125650

First of all, you have to make your interface generic:

public interface IDataGateway<T>

and then specify T while implementing it:

public class LibraryGateway : IDataGateway<Media>

Upvotes: 0

Mehrdad Afshari
Mehrdad Afshari

Reputation: 422270

You are declaring the type argument on each method individually. You should declare it on the interface type itself.

public interface IDataGateway<T>
{
    void InsertRow(T row);
    void UpdateRow(T row);
    IEnumerable<T> GetTable(T table);
}

public class LibraryGateway : IDataGateway<Media>
{
    public void InsertRow(Media item) { }
    public void Updaterow(Media item) { }
    public IEnumerable<Media> GetTable() { }
}

To clarify, your current implementation could be rewritten as:

public interface IDataGateway
{
    void InsertRow<T>(T row);
    void UpdateRow<U>(U row);
    IEnumerable<V> GetTable(V table);
}

That is, there is no requirement for T to be the same as U and V. Each method is genericized by its own type parameter, but the containing interface type itself is not generic.

By declaring the type argument on the type itself, you restrict the type arguments of the methods to be identical when implemented by a subclass. In C++ terms, which you seem to be familiar with, your current implementation is analogous to three separate template functions whereas my implementation is more similar to a template class.

Upvotes: 2

Related Questions