2016-08-17 46 views
0

考慮以下代碼:型專用靜態

public class Person 
{ 
    public string Name { get; set; } 
} 

public class Animal 
{ 
    public string Name { get; set; } 
} 

public interface IHandler<T> 
{ 
    T Handle(T eventData); 
} 

public class UpdatePersonHandler : IHandler<Person> 
{ 
    public Person Handle(Person eventData) 
    { 
     var test = eventData.Name; 
     return eventData; 
    } 
} 
public class UpdatePersonHandler2 : IHandler<Person> 
{ 
    public Person Handle(Person eventData) 
    { 
     var test = eventData.Name; 
     return eventData; 
    } 
} 
public class UpdateAnimalHandler : IHandler<Animal> 
{ 
    public Animal Handle(Animal eventData) 
    { 
     var test = eventData.Name; 
     return eventData; 
    } 
} 

public class Bus<T> 
{ 
    public static readonly IList<IHandler<T>> Handlers = new List<IHandler<T>>(); 

    public static void Register(IHandler<T> handler) 
    { 
     if (handler != null) 
      Handlers.Add(handler); 
    } 

    public static void Raise(T eventData) 
    { 
     foreach (var handler in Handlers) 
     { 
      handler.Handle(eventData); 
     } 
    } 
} 

這個測試代碼:

[TestMethod] 
public void TestRegister() 
{ 
    Bus<Person>.Register(new UpdatePersonHandler()); 
    Bus<Person>.Register(new UpdatePersonHandler()); 
    Bus<Person>.Register(new UpdatePersonHandler2()); 

    Bus<Animal>.Register(new UpdateAnimalHandler()); 

    Debug.Print(Bus<Person>.Handlers.Count.ToString()); 
    Debug.Print(Bus<Animal>.Handlers.Count.ToString()); 
} 

這個測試的輸出:

3 
1 

是什麼去這裏?

它看起來好像框架正在爲通過static註冊方法呈現給它的每種類型新建一個總線類。爲此,它必須爲每個新類型調用Bus<T>的默認構造函數。

但是爲什麼?這個怎麼用?

這是否有任何實際的用途,或者它只是一個有趣的,但令人遐想的C#應該在生產代碼中避免的好奇心?

+0

對話[轉移到聊天](http://chat.stackoverflow.com/rooms/121216/discussion-between-robert-harvey-and-peter-duniho)。 –

回答

3

是的,傳遞給靜態類Bus<T>的每種不同類型都會導致調用默認構造函數。驗證這一個簡單的方法是給它一個默認的構造函數:

static Bus(){ Debug.Print("ctor"); } 

使用這將產生輸出

ctor 
ctor 
3 
1 

這樣做的原因是,泛型類僅用於類模板,這是靜態類仍然如此。一旦泛型類型被賦予了Bus類,那麼模板就被物化爲一個類,這就是構造函數被調用的時候。

該物化類對於同一類的其他通用類型是唯一的。因此,當使用Bus<Person>Bus<Animal>時,這些實際上是單獨的類,具有單獨的靜態成員數據,並且需要單獨實例化。

至於使用與普通的打字靜態字段的前景,有一個MSDN警告(顯然ReSharper的本來就撿起)

CA1000:不要在泛型類型
聲明靜態成員https://msdn.microsoft.com/en-us/library/ms182139(VS.80).aspx

+1

微軟似乎認爲這種做法存在的問題是它會擾亂類型推斷。該類的多個實例(每個類型一個)似乎並沒有打擾他們。 「按設計」,就像它一樣。 –

+0

@RobertHarvey:_「這個類的多個實例(每個類型一個)似乎並沒有打擾他們」 - 完全,也不應該。甚至類型推斷的問題都值得商榷。如果在一天結束時,你需要的是一個靜態泛型類,或者一個沒有任何泛型參數的泛型方法,那就是你需要做的。它確實發生了(一個例子是處理'enum'類型的輔助方法)。請注意,擴展方法可以減輕_some_這種情況的痛苦。 –

+0

不錯,我現在明白了 – ShaneKm