通用接口返回Task <t>

时间:2018-01-02 23:44:54

标签: c# .net generics

我想有这样的界面:

public interface IQuery       // I do NOT want IQuery<T>
{
    Task<T> Result();         // Only this line can change
}

这可能吗?

这种变化的原因是Query<T>IQuery,下面的代码有效,但是在那里有任务,会导致&#39; q&#39;空值。动态的东西不再有效。所以要解决这个问题,我必须没有约束public Action(object obj) { ... var q = obj as IQuery<dynamic>; // Having Query<T> q is NULL - bad! Query = new Optional<IQuery<dynamic>>(q); }

public interface IQuery<T>
{
    Task<T> Result();
}

编辑: enter image description here

编辑2: 有没有办法让IQuery这样:

var q = obj as IQuery<dynamic>;

并使这项工作?

public class GetReminder : IQuery<ReminderDb>
{

    public override async Task<ReminderDb> Result()
    {
        // read from db and return

        ...
}

whre obj就是这个类:

System.out.print()

3 个答案:

答案 0 :(得分:3)

可能但是以这种方式

public interface IQuery     // I do NOT want IQuery<T>
{
    Task<T> Result<T>(); // Only this line can change
}

答案 1 :(得分:3)

原来的问题:
是的,您可以在没有泛型参数的情况下定义您的界面,并且仍然使其具有带有通用参数的方法,就像@MegaTron回答一样。

将您的新问题放入编辑中:
你肯定可以返回任务。这只是你的方法定义出错了 我想你想要的是:

public override async Task<T> Result<T>() where T : new() // or T : ReminderDb?
{
    var t = new T();
    // do what you want with t...
}

使用方法:

var task = resultGenerator.Result<ReminderDb>();

您不能使用ReminderDb作为通用参数的名称(也就是说,您不能编写public override async Task<ReminderDb> Result<ReminderDb>()),因为IDE建议会隐藏类ReminderDb

编辑1:
关于我对问题的第一个编辑部分的回答的更多解释:

在C#中,您可以对您使用的通用参数设置约束 约束是指我的代码示例中的where T : new()部分 正如您可能猜到的,约束要求您将使用任何类型T来调用此方法,T必须具有new-ed的能力(具有公共无参数构造函数且不是抽象类) )。

我使用的约束在您的情况下是强制性的,因为在问题中,此方法的第一行会新闻T的实例。
请设想,如果未应用约束,编译器无法确保用于调用方法的类型必须能够通过new T()创建新实例。

您可能需要的另一个可能的约束是直接要求泛型参数继承自ReminderDb 但是,正如@Camilo Terevinto建议的那样,如果此方法使用的唯一可能类型(而不是其派生类型)为ReminderDb,则根本不需要泛型参数。

答案 2 :(得分:2)

你想要的是这个:

extension FixedWidthInteger {
    init<Bytes: Sequence>(bytes: Bytes, littleEndian: Bool = false) where Bytes.Element == UInt8 {
        var s: Self = 0

        let width = Self.bitWidth / 8

        for (i, byte) in bytes.enumerated() where i < width {
            let shiftAmount = (littleEndian ? i : (width - 1 - i)) * 8

            s |= (Self(truncatingIfNeeded: byte) << shiftAmount)
        }

        self = s
    }
}

然后执行如下:

public interface IQuery
{
    Task<T> Result<T>();
}

public class GetReminder : IQuery { public async Task<T> Result<T>() where T: ReminderDb, new() { return await Task.FromResult(new T()); // return a new instance } } 约束将在编译时限制ReminderDb或任何实现它的类型,而ReminderDb约束将允许您使用无参数构造函数。 / p>

然后你会用:

来调用它
new()