2016-01-25 14 views
4

对于C#中的泛型接口类型制定约束会有什么意义?例如,为什么在通用打字中限制界面?

public interface IHandler<in T> where T : IProcessor 
{ 
    void Handle(T command); 
} 

简单地继承IP processor作为通用没有任何约束不是更好吗?这样做的好处是什么?

例如,

public class Test: IProcessor<T>{void Handle(T command);} 
+0

这是一个相当不常见的用法。看到类似'公共类ProcessorHandler :IHandler 其中T:IProcessor' –

+4

我不太明白'你的意思是'继承IProcessor作为通用'。你能解释一下吗? – Max

+0

公共类测试:IProcessor user1789573

回答

1

如果接口是空白,则它是一个marker interface

它可以用于在班级之外应用有关班级的限制。按照下面的示例,您可以限制装饰器只能装饰IProcessor的处理程序。


一个非常有效的原因是应用装饰时:

假设命令参数界面有几个特性:

public interface IProcessor 
{ 
    int Id { get; } 
    DateTime Date { get; } 
} 

我们可以超过IProcessor所有处理程序定义一个装饰知道所有命令参数都具有IdDate的命令:

public sealed class HandlerLogger<in T> where T : IProcessor 
{ 
    private readonly ILogger logger; 
    private readonly IHandlerLogger<T> decorated; 

    public HandlerLogger(
     ILogger logger, 
     IHandlerLogger<T> decorated) 
    { 
     this.logger = logger; 
     this.decorated = decorated; 
    } 

    public void Handle(T command) 
    { 
     this.logger.Log(command.Id, command.Date, typeof(T).Name); 
     this.decorated.Handle(command); 
    } 
} 
+0

是的,如果它是一个具体的类,并且IProcessor有声明的成员,我会得到它。但是,我正在使用一个已经完成的项目,只是试图维护代码。这就是说 - 在我的项目中,接口IP处理器是空的,处理程序是一个接口(并不是什么大不了的)。如果IP处理器是空的,将其作为约束条件的优势是什么? – user1789573

+2

在这种情况下,这是[标记约束](http://stackoverflow.com/questions/1023068/what-is-the-purpose-of-a-marker-interface) – qujck

0

有不同的体系结构模式可用于实际执行类型。例如,如果你正在设计一个API,并且你想允许某人扩展它,但是你想确保正在创建的用于扩展你的框架的类是一个特定的类型并且有一个默认的无参数构造函数。使用泛型类型接口是一种常见的方法。

我创建了一个简单的例子来给出一个相对简单的概述为什么在某些模型/体系结构设计中键入的界面是有用的。

public class UnitOfWorkManager<T> 
{ 
    private readonly IDataRepository _dataRepository; 
    private List<T> _unitOfWorkItems; 

    public UnitOfWorkManager(IDataRepository dataRepository) 
    { 
     _dataRepository = dataRepository; 
    } 

    public void AddUnitOfWork(IUnitOfWork<T> unitOfWork) 
    { 
     this._unitOfWorkItems.Add(unitOfWork); 
    } 

    public void Execute() 
    { 
     WorkerItem previous = null; 
     foreach (var item in _unitOfWorkItems) 
     { 
      var repoItem = _dataRepository.Get(item.Id); 
      var input = new WorkerItem(item.Id, repoItem.Name, previous); 
      previous = input; 
     } 
    } 
} 

public interface IUnitOfWork<T> 
    where T: WorkerItem, new() 
{ 
    string Id { get; } 
    void Execute(T input); 
} 

public class WorkerItem 
{ 
    public WorkerItem(string id, string name, WorkerItem previous) 
    { 
     this.Name = name; 
     this.Id = id; 
     this.Previous = previous; 
    } 
    public string Id { get; private set; } 
    public string Name { get; private set; } 
    public WorkerItem Previous { get; private set; } 
} 

希望这会有所帮助。

相关问题