2016-01-25 16 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; } 
} 

希望這會有所幫助。

相關問題