C# 泛型接口,泛型接口与泛型

C# 泛型接口,泛型接口与泛型,c#,generics,C#,Generics,我的问题中有很多泛型,我希望它仍然可以理解 我有以下接口: public interface ICommandBus { TResult Publish<TCommand, TResult>(TCommand command) where TResult : ICommandResult where TCommand : ICommand<TResult>; } public interface ICommand<T>

我的问题中有很多泛型,我希望它仍然可以理解

我有以下接口:

public interface ICommandBus
{
    TResult Publish<TCommand, TResult>(TCommand command)
        where TResult : ICommandResult
        where TCommand : ICommand<TResult>;
}

public interface ICommand<T>
    where T : ICommandResult
{ }

public interface ICommandResult
{
    bool Success { get; }
}
编辑:更新Lucas答案

Lucas解决方案应该可以工作,但我仍然必须将
where-TResult:ICommandResult
约束置于其中,以避免错误
从'TResult'到'Core.Command.ICommandResult'没有装箱转换或类型参数转换。

我在继承方面也有一个很大的问题,假设我有以下抽象命令:

public abstract class NotificationObserver<TResult> : ICommandObserver<TResult>
    where TResult : ICommandResult
{
    protected virtual bool IsEnable(ICommand<TResult> command, TResult result)
    {
        return true;
    }
}
公共抽象类NotificationObserver:ICommandObserver
其中TResult:ICommandResult
{
受保护的虚拟bool是可启用的(ICommand命令,TResult结果)
{
返回true;
}
}
它的实现

public class CreateItemObserver : NotificationObserver<CreateItemResult>
{
    protected override bool IsEnable(CreateItemCommand command, CreateItemResult result)
    {
        return !String.IsNullOrEmpty(command.Name);
    }
}
公共类CreateItemObserver:NotificationObserver
{
受保护的覆盖布尔IsEnable(CreateItemCommand命令,CreateItemResult)
{
return!String.IsNullOrEmpty(command.Name);
}
}
这将不起作用,因为实现没有真正覆盖虚拟方法(不是相同的签名:
ICommand
!=
CreateItemCommand


如果我保留了正确的签名,我就不能在实现中使用CreateItemCommand属性而不使用难看的强制转换…

您可以像这样轻松地重写您的界面,以摆脱
TCommand
参数:

public interface ICommandBus
{
    TResult Publish<TResult>(ICommand<TResult> command)
        where TResult : ICommandResult;
}
我猜C#拒绝推断您案例中的类型参数的原因是
TCommand
可以多次实现
ICommand
,如下所示:

var result = commandBus.Publish<CreateItemCommand, CreateItemResult>(command); //Works, but ugly...
public class SomeCommand : ICommand<Foo>, ICommand<Bar>
{
    // ...
}
公共类SomeCommand:ICommand,ICommand
{
// ...
}

您可以像这样轻松地重写界面,以摆脱
t命令
参数:

public interface ICommandBus
{
    TResult Publish<TResult>(ICommand<TResult> command)
        where TResult : ICommandResult;
}
我猜C#拒绝推断您案例中的类型参数的原因是
TCommand
可以多次实现
ICommand
,如下所示:

var result = commandBus.Publish<CreateItemCommand, CreateItemResult>(command); //Works, but ugly...
public class SomeCommand : ICommand<Foo>, ICommand<Bar>
{
    // ...
}
公共类SomeCommand:ICommand,ICommand
{
// ...
}

我在这里看到一种非专利药过量;)太多的泛型,在这些泛型中,简单的继承会给您带来更容易的结果

如果您想在不完全重构的情况下使用类来摆脱太多的泛型:您只需要指定泛型函数调用,因为编译器不够智能,无法为您这样做(自动解析泛型参数是可以的,解析泛型参数的泛型参数不是)

var result=commandBus.Publish(命令);

它很重,不是特别优雅,但至少它能用。另一方面,您的接口声明本身很重,因此使用它也很重也就不足为奇了。

我在这里看到泛型过量;)太多的泛型,在这些泛型中,简单的继承会给您带来更容易的结果

如果您想在不完全重构的情况下使用类来摆脱太多的泛型:您只需要指定泛型函数调用,因为编译器不够智能,无法为您这样做(自动解析泛型参数是可以的,解析泛型参数的泛型参数不是)

var result=commandBus.Publish(命令);

它很重,不是特别优雅,但至少它能用。另一方面,您的接口声明本身很重,因此使用它也很重也就不足为奇了。

所有泛型的意义是什么?将泛型和专门化都用于某个接口似乎会适得其反……我认为这就是重点。。。我滥用了泛型,现在我被卡住了……编辑中的后续问题是它自己的问题,所以如果你想得到答案,你应该单独发布。你想在这里做双重分派,也许你应该试试。所有泛型的意义是什么?将泛型和专门化都用于某个接口似乎会适得其反……我认为这就是重点。。。我滥用了泛型,现在我被卡住了……编辑中的后续问题是它自己的问题,所以如果你想得到答案,你应该单独发布。您正在尝试在此处执行双重分派,也许您应该尝试.True,您可以删除
where-TResult:ICommandResult
约束,但我会保留它。是的,这是多余的,但是约束在那里,无论你做什么,所以明确地写下它会使代码更容易阅读和理解。有时冗余很好。无法删除此约束,因为
没有从'TResult'到'Core.Command.ICommandResult'的装箱转换或类型参数转换。
。此错误出现在
Publish
方法上。我认为在这种情况下,我应该使用
in
out
修饰符,但我不太理解它们…@jbuiss0n您可以保持约束不变,或者如果您知道
TResult
是一个类,您可以使用
约束,或者如果您想摆脱这里的约束,您可以这样编写一个双重强制转换:
(TResult)(object)命令来绕过错误。我更喜欢避免双重强制转换,我认为当您阅读并试图理解代码时会很痛苦。我还更新了这个问题,因为您的解决方案部分有效,因为在我的情况下,我还必须管理继承…没错,您可以删除
where-TResult:ICommandResult
约束,但我会保留它。是的,这是多余的,但是约束在那里,无论你做什么,所以明确地写下它会使代码更容易阅读和理解。有时冗余很好。无法删除此约束,因为
没有从'TResult'到'Core.Command.ICommandResult'的装箱转换或类型参数转换。
。此错误出现在
Publish
方法上。我认为在这种情况下,我应该使用
in
out