[英]Generics: How to check the exact type of T, without object for T
如何在沒有T的對象的情況下檢查/評估T的確切類型。我知道我的問題可能令人困惑,但請考慮一下......
public abstract class Business
{
public abstract string GetBusinessName();
}
public class Casino : Business
{
public override string GetBusinessName()
{
return "Casino Corp";
}
}
public class DrugStore : Business
{
public override string GetBusinessName()
{
return "DrugStore business";
}
}
public class BusinessManager<T> where T : Business
{
private Casino _casino;
private DrugStore _drugStore;
public string ShowBusinessName()
{
string businessName;
if (T == Casino) // Error: How can I check the type?
{
_casino = new Casino();
businessName = _casino.GetBusinessName();
}
else if (T == DrugStore) // Error: How can I check the type?
{
_drugStore = new DrugStore();
businessName = _drugStore.GetBusinessName();
}
return businessName;
}
}
我只是想在客戶端上有這樣的東西。
protected void Page_Load(object sender, EventArgs e)
{
var businessManager = new BusinessManager<Casino>();
Response.Write(businessManager.ShowBusinessName());
businessManager = new BusinessManager<DrugStore>();
Response.Write(businessManager.ShowBusinessName());
}
請注意,當我調用BusinessManager時,我實際上沒有為Casino和Drugstore創建實際對象,我只是將其作為類的泛型類型約束傳遞。 我只需要知道我正在傳遞什么類型的BusinessManager來知道要實例化的Type究竟是什么 。 謝謝...
PS:我不想為Casino和Drugstore創建單獨的特定BusinessManager。
您還可以對設計發表評論..謝謝..
附加:如果類Casino和DrugStore是抽象類=如果=)
你可以寫
if(typeof(T) == typeof(Casino))
但實際上這種邏輯是一種代碼味道。
這是解決這個問題的一種方法:
public class BusinessManager<T> where T : Business, new() {
private readonly T business;
public BusinessManager() {
business = new T();
}
}
但我個人更喜歡
public class BusinessManager<T> where T : Business {
private readonly T business;
public BusinessManager(T business) {
this.business = business;
}
public string GetBusinessName() {
return this.business.GetBusinessName();
}
}
你應該做
public class BusinessManager<T> where T : Business, new()
...
T _business = new T();
string businessName = _business.GetBusinessName();
return businessName;
我不知道C#語法,但是不可能這樣做:
public class BusinessManager<T> where T : Business, new()
{
private T _business;
public string ShowBusinessName()
{
string businessName;
_business = new T();
return _business.GetBusinessName();
}
}
由於其他人已經對你的第一個問題給出了各種答案,我想談談第二個問題:設計。
1. BusinessManager
角色
BusinessManager
類在示例中的實際角色不太清楚。 由於這個類是通用的,並且它不應該關注T
的實際類型,因此它只是在Business類和程序的其余部分之間添加另一個不必要的層。
換句話說,您可以簡單地使用:
Business casino = new Casino();
Response.Write(casino.GetBusinessName());
Business drugStore = new DrugStore();
Response.Write(drugStore.GetBusinessName());
將它包含在另一個泛型類中對你沒有多大幫助。 另一方面,如果要為所有這些類提供一些通用功能,可以將其直接添加到抽象類中,也可以提取接口並為該接口創建擴展方法。
2.使用吸氣劑的屬性
第二,使用簡單的getter方法時,使用屬性更合適。 換句話說,你應該用Name
屬性替換GetBusinessName()
方法(我也從名稱中省略了“Business”,因為沒有必要:
public interface IBusiness
{
string Name { get; }
}
public abstract class Business : IBusiness
{
public abstract string Name { get; }
}
public class Casino : Business
{
public override string Name
{
get { return "Casino Corp"; }
}
}
public class DrugStore : Business
{
public override string Name
{
get { return "DrugStore business"; }
}
}
然后你可以像這樣使用它:
IBusiness casino = new Casino();
Response.Write(casino.Name);
IBusiness drugStore = new DrugStore();
Response.Write(drugStore.Name);
此外,您可以看到我已經引入了IBusiness
接口。 這樣做的原因是允許您以更多樣化的方式實現此接口。 現在,您將嘗試從抽象Business
類派生所有類,並嘗試在抽象類中提取盡可能多的常用功能(這是類的目的)。
但是,提取大量常用功能需要付出代價:您總是有可能需要創建一個不是從Business
派生的類。 如果您通過IBusiness
接口訪問所有這些方法,那么程序的其他部分將不關心該實現是否來自Business
。
由於GetBusinessName確實適用於類型而非類型實例,因此您可以考慮使用DescriptionAttribute(或您自己的BusinessNameAttribute)而不是重寫屬性,並讓BusinessManager從屬性中獲取業務名稱。
[Description("Casino Corp")]
public class Casino : Business
{
}
現在,您不再需要實例化業務只是為了得到它的名字。 要獲得描述,請使用:
public string ShowBusinessName()
{
var attribute = Attribute.GetCustomAttribute(typeof(T), typeof(DescriptionAttribute)) as DescriptionAttribute;
if (attribute == null)
return "Unknown business";
return attribute.Description;
}
你可以這樣做:
if (typeof(T) == typeof(SomeType))
{
// Same
}
將BusinessManager
類定義為:
public class BusinessManager<T> where T : Business
{
Business biz;
public BusinessManager()
{
biz = new T();
}
public string ShowBusinessName()
{
return biz.GetBusinessName();
}
}
並使用它如下:
var businessManager = new BusinessManager<Casino>();
Response.Write(businessManager.ShowBusinessName());
var anotherBusinessManager = new BusinessManager<DrugStore>();
Response.Write(businessManager.ShowBusinessName());
你使用它的方式將失去封裝
在VB.net中,您可以在泛型類型參數上使用GetType偽函數來獲取反射Type對象。 我猜C#應該有一個等價物。 如果由於某種原因你不能使用類似的東西,你可以創建一個包含所需類型的0個元素的數組,然后檢查該數組的類型。 這可能比實例化未知類型的元素便宜。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.