tags:

views:

351

answers:

3

I thought I'd use some (what I thought was) simple generics to enforce CRUD on some Business Classes. eg.

public interface IReadable <T>
{
    T Read<T>(string ID);
}

and then perhaps, I could have a NoteAdapter to do C**R**UD with the Note class eg.

public class NoteAdapter : IReadable<Note>
{
    public Note Read<Note>(string ID) {
        return new Note();
    }
}

But for some reason, te compiler is getting confused if I have both a generic return Type and a function Parameterized with the same generic Type. That is , if I do :

public interface IReadable <T>
{
    void Read<T>(string ID);
}
public class NoteAdapter : IReadable<Note>
{
    public void Read<Note>(string ID) {
        return new Note();
    }
}

It compiles fine, although it doesnt do what I want it to ! Also, this :

public interface IReadable <T>
{
    T Read (string ID);
}
public class NoteAdapter : IReadable<Note>
{
    public Note Read(string ID) {
        return new Note();
    }
}

works fine as well, Although it too does not satisfy the requirements ! -- Why ? Because then I can't have one Class that implements a bunch of these Interfaces ..eg.

public interface IReadable <T>{
    T Read (string ID);
}
public class UniversalAdapter : IReadable<Note>, IReadable<Customer> ...
{
    public Note Read(string ID) {
        return new Note();
    }
    public Customer Read(string ID) {
        return new Customer();
    }
}

Coz this would not compile as return types are not part of the methods signature !

I was under the impression, in C# 3.5 +

T Foo(T t);
T Foo<T> (T t);
T Foo(<SomeType> someInstance);

All have different signatures! What am I missing here ?

+3  A: 

public interface IReadable <T> { T Read<T>(string ID); }

here really two different Ts : IReadable <T> and T Read<T>(string ID)

maybe just

public interface IReadable <T> { T Read(string ID); } ?

because otherwise is equal to

public interface IReadable <T> { X Read<X>(string ID); }

Good Generics tutorial

EDIT:

May be you need public interface IReadable <T> { T Read(T ID); } ?

Trickster
Yeah, to be specific, you need: public interface IReadable <T> { T Read (string ID); }So there's only one actual generic parameter here, the T for the interface type definition.
Pete
See.. that would compile, but it's not what I am looking for.. as I will probably have ONE adapter class that will implement a bunch of IReadable<T>s e.g. IReadable<Note>, IReadable<Customer> etc.. and that would not work as all those "T Read (string ID)"s will evaluate to the same function i.e it wil not allow "Note Read(string ID);" and also "Customer Read(string ID)" in the same class ! ~As always..thx for your help !
IM
public interface IReadable <T> { T Read(T ID); } ?
Trickster
A: 

The CIL does not support method overloading by return type.

Darin Dimitrov
u're right buddy.. my bad.. I removed the bad example, but my point was that it I Do Interface<T> { T Read<T>{string id) } - it seems to be able to match only one of the Methods ReturnType OR the Methods Parameter <T> with the Interface's Type <T> , but not both !Thx for ur time !
IM
+5  A: 

You've overspecified the interface. You declare T in the interface definition, but then you redeclare it in the method's definition:

public interface IReadable <T>  /* T is declared here */
{
    T Read<T>(string ID); /* here, you've declare a NEW generic type parameter */
                          /* that makes this T not the same as the T in IReadable */
}

Due to this confusion, you end up with an error when you try to implement the interface.

public class NoteAdapter : IReadable<Note> /* IReadable defines T to be Note */
{
    public Note Read<Note>(string ID) { /* Here, you're declaring a generic parameter */
                                        /* named Note.  This name then conflicts with */
                                        /* the existing type name Note */
        return new Note();
    }
}

To fix this, you simply need to remove the generic parameter from the Read function, both in the interface, and in the NoteAdapter class:

public interface IReadable <T>
{
    T Read(string ID);
}
public class NoteAdapter : IReadable<Note>
{
    public Note Read(string ID) {
        return new Note();
    }
}

EDIT:

Okay, I read the rest of your post, and it seems that you've already discovered that this "works", but you seem to think it's incorrect. Why? What requirements does this not meet?

P Daddy
Thx for ur help.. it is not that I thought what worked was incorrect, but that my expectation was the the CLR would equate the two generic types.. the one one the Interface and the One on the Method.. i.e. Interface <T>'s T would be the same as T Read<T> 's return type <T> as well as the Read<T>; but in reality, it only matches Interface<T>'s "T" with the return Type
IM