c# - 使用另一个接口(interface)从一个接口(interface)实现泛型方法

标签 c# generics interface

我正在尝试创建一个通用接口(interface),它允许我使用 n 种方法与数据库进行交互。我希望我的业务应用程序能够实例化任何连接方法并确保接口(interface)是相同的。

这是我现在尝试的简化版本。

数据库接口(interface),其中 IElement 是另一个定义表的接口(interface)。

public interface IDatabase
{
    void setItem( IElement task );  //this works fine
    List<T> listTasks<T>() where T : IElement; // this doesn't
}

IElement 接口(interface):

public interface IElement
{
    int id { get; set; }
}

IElement 的实现:

public class TaskElement: IElement
{
    public int id { get; set; }
    public string name {get; set; }
}

IDatabase 的实现:

public class SQLiteDb: IDatabase
{
    public SqLiteDb( SQLiteConnection conn )
    {
        database = conn;
    }

    public void setItem( IElement task )
    {
        // works fine when passed a new TaskElement() which is an implementation of IElement.
        database.Insert( task ); 
    }

    //it all goes off the rails here
    public List<T> listItems<T>() where T : IElement
    {
        var returnList = new List<IElement>

        foreach (var s in database.Table<TaskElement>())
        { returnList.Add(s); }

        return returnList;
    }

我已经尝试了很多变体,但每一个都给我一个新问题。例如,这里有两个错误。

1)

The type arguments for method 'SQLiteDb.listTasks<T>()' cannot be inferred from the usage. Try specifying the type arguments explicitly.

2)

Cannot implicitly convert type 'System.Collections.Generic.List<TaskElement>' to 'System.Collections.Generic.List<T>'

我曾尝试更改方法以使用显式类型,但在那里遇到了问题。如果我使用 IElement(我的所有元素的通用接口(interface))我不能返回 TaskElement 对象的列表(我的 IElement 的实现)因为它不匹配返回类型(List<IElement>)并且如果我将返回类型更改为 List<TaskElement> I '不再实现接口(interface)。

值得注意的是,如果我停止使用接口(interface)和泛型,我可以很容易地让它工作,但这似乎是使用接口(interface)的理想情况。也许当另一个应用程序(如直接继承)可能更好时,我正在努力将很多东西塞进一个接口(interface)?

问题

如何实现具有通用返回值的接口(interface),同时将可返回的类型限制为仅实现另一个接口(interface)。

最佳答案

让我们仔细看看您对 listItems 的实现:

public List<T> listItems<T>() where T : IElement
{
    var returnList = new List<IElement>

    foreach (var s in database.Table<TaskElement>())
    { returnList.Add(s); }

    return returnList;
}

你在这里所做的是编写一个方法,允许调用者在列表中请求他们想要的任何类型,只要该类型实现了 IElement。 .但是你方法中的代码没有给他们一个他们想要的类型的列表,它给了他们一个 IElement 的列表。 .所以它违反了契约(Contract)。

但问题的真正根源是 database.Table<TaskElement>() .那只能给你 TaskElement 的实例.你需要做那个 T ,但要做到这一点,您需要一个额外的通用约束:

public List<T> listItems<T>() where T : IElement, new
{
    var returnList = new List<T>

    foreach (var s in database.Table<T>())
    { 
        returnList.Add(s); 
    }

    return returnList;
}

这是因为 database.Table<T>有一个 new约束,这意味着它只能被赋予具有零参数构造函数的类型(因为该方法将创建给定类的实例)。

关于c# - 使用另一个接口(interface)从一个接口(interface)实现泛型方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38703081/

相关文章:

c# - 从 TreeView 检索节点上的绑定(bind)对象

c# - 在 C# 中使用 Post 下载附件文件

c# - 菜单控件 CSS 在 UpdatePanel 内时中断

c# - ' 4' and ' 4' 主键冲突但文件系统不冲突

generics - 苹果 swift : Generic type constraint for String type only not works

.net - 在.NET中使用反射调用泛型方法

c# - 通用类和 IEquatable 问题

java - 参数内的泛型类型

go - 反射(reflect)接口(interface)列表

.net - 如何在.net的程序集中查找特定接口(interface)的所有类