C# 接口<T> { T Func<T>(T t);} :带有参数化方法和泛型返回类型的通用接口

13
我想使用一些(我认为是)简单的泛型来强制实施对一些业务类的CRUD操作。 例如:
public interface IReadable <T>
{
    T Read<T>(string ID);
}

然后,也许我可以使用NoteAdapter来对Note类进行增删改查(CRUD)操作。

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

但出于某种原因,编译器会混淆同时有泛型返回类型和使用相同泛型类型参数化的函数,例如:

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

它可以编译通过,但它并没有实现我想要的功能!另外,这个:
public interface IReadable <T>
{
    T Read (string ID);
}
public class NoteAdapter : IReadable<Note>
{
    public Note Read(string ID) {
        return new Note();
    }
}

虽然这种方法也能正常工作,但它并不能满足要求!--为什么? 因为我无法创建一个类来实现一组这些接口, 例如:

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

因为返回类型不是方法签名的一部分,所以这段代码将无法编译!

我认为,在C#3.5+中可以实现。

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

所有的签名都不同!我在这里漏掉了什么?
3个回答

19
你过度指定了接口。在接口定义中声明了 T,但是在方法的定义中又重新声明了它:
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 */
}

由于这种混淆,当你尝试实现接口时会出现错误。
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();
    }
}

为了解决这个问题,你只需要从接口和NoteAdapter类的Read函数中删除泛型参数:

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

编辑:

好的,我已经阅读了您帖子的其余部分,似乎您已经发现这个方法“可行”,但您似乎认为它是不正确的。为什么?这种方法有哪些要求无法满足?


谢谢您的帮助。我并不是认为我的代码有问题,而是我期望CLR会将两个泛型类型相等。一个是接口上的泛型类型,另一个是方法中的泛型类型。也就是说,接口<T>中的T应该与Read<T>方法的返回类型<T>以及Read<T>方法中的<T>相同。但实际上,它只匹配了接口<T>中的“T”和返回类型。 - IM.

3

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

这里有两个不同的T:IReadable <T> 和 T Read<T>(string ID)

也许只需要

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

因为否则就等于

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

好的泛型教程

编辑:

也许你需要public interface IReadable <T> { T Read(T ID); }


是的,具体而言,您需要:public interface IReadable { T Read (string ID); }所以这里只有一个实际的泛型参数,即接口类型定义的 T。 - Pete
看起来这段代码可以编译通过,但不符合我的要求。我可能只需要一个适配器类来实现一堆IReadable<T>,例如IReadable<Note>、IReadable<Customer>等等。如果这样做,所有的“T Read (string ID)”都会被解释为相同的函数,也就是说在同一个类中无法同时实现“Note Read(string ID);”和“Customer Read(string ID)”! ~感谢您的帮助! - IM.
公共接口 IReadable <T> { T Read(T ID); } - Ilya Khaprov

2
CIL不支持按返回类型重载方法。

你是对的伙计..我的错..我已经删除了不好的例子,但我的观点是,如果我有一个接口 Interface<T> { T Read<T>{string id) } - 它似乎只能匹配方法的返回类型或方法的参数 <T> 与接口的类型 <T> 中的一个,而不能同时匹配两者!谢谢你的时间! - IM.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接