2009-06-04 23 views
2

剛剛發現有點代碼這裏有人寫訪問某些數據庫實體...使用`其中T:SOMETHING`構建C#

public static OurCustomObject GetOurCustomObject(int primaryKey) 
{ 
    return GetOurCustomObject<int>(primaryKey, "usp_GetOurCustomObjectByID"); 
} 

public static OurCustomObject GetOurCustomObject(Guid uniqueIdent) 
{ 
    return GetOurCustomObject<Guid>(uniqueIdent, "usp_GetOurCustomObjectByGUID"); 
} 

private static OurCustomObject<T>(T identifier, string sproc) 
{ 

    if((T != typeof(int)) && (T == typeof(Guid))) 
    { 
     throw new ArgumentException("Identifier must be a string or an int"); 
    } 

    //ADO.NET Code to make DB Call with supplied sproc. 
} 

的Theres只是一些事情似乎並不很generic。 sprocs傳入內部方法的事實感覺很難看。但我周圍看到的唯一途徑是的if/else沿的

if(type == int) 
    sproc = "GetByID"; 
else if (type == Guid) 
    sproc = "GetByGUID"; 

行私有方法同樣的異常拋出長相醜陋也有一個......反正是有使用其中T :子句

例如

private static OurCustomObject<T>(T identifier) where T : int OR Guid 

有關如何清理這一點的任何建議。

+0

你在方法的機身採用「T」的呢? – 2009-06-04 15:36:03

+0

就是這樣,它並沒有被專門使用。有typeof(T)== typeof(int)檢查,然後他們只是使用SQL Helper調用執行SPROC,並將標識符作爲參數傳遞。這就是爲什麼我只是覺得用法感覺有點被迫 – 2009-06-04 18:33:51

+0

然後我同意你,這似乎是一個糟糕的設計。通用方法的目的就是GENERIC。只能是兩件事的「通用」不是非常通用的。如果你不用T來做其他事情,那麼你唯一可能使用的「標識符」 - 一個不受約束的T - 在體內就是一個System.Object。爲什麼不完全消除通用性,只是把「標識符」作爲一個對象? – 2009-06-04 20:18:19

回答

8

你不能指定一個約束「它是這兩個之一」,否。

什麼你可能做的是:

Dictionary<Type, string> StoredProcedureByType = new Dictionary<Type, string> 
{ 
    { typeof(Guid), "GetByGUID" }, 
    { typeof(int), "GetByID" } 
}; 

然後使用:

string sproc; 
if (!StoredProcedureByType.TryGetValue(typeof(T), out sproc)) 
{ 
    throw new ArgumentException("Invalid type: " + typeof(T).Name); 
} 

這可能是矯枉過正的只是一對夫婦的類型,但它很好地進行擴展,如果你有很多的涉及的類型。

鑑於這兩種類型是值類型,你可以把它更穩健與約束:

where T : struct 

,但將仍然允許byte

0

沒有支持對於這樣的where子句以這種方式限制類型參數(不幸的是)。

在這種情況下,你可能會發現,經過identifier爲對象,並使用泛型實際上是清潔劑(當我需要類似的東西,這就是我最後做:似乎是最差勁的方法) 。

這是一個C#很弱的領域,既不是一種動態語言,也不能專門化模板(C++就像,只提供T = int和T = Guid的實現)。

附加:在這種情況下,我可能會堅持重載,但將類型檢查更改爲Assert,因爲這是一種私人幫助方法。

2

您提供的代碼看起來相當不錯,因爲private static OurCustomObject<T>(T identifier, string sproc)是私人的。我甚至會從這個方法中刪除異常檢查,因爲再次 - 它是私有的,所以這個類控制傳遞給方法的東西。 if語句會非常可怕並且過度設計。

1

做的是可能做這樣的事情最巧妙的事情:

public interface IPrimaryKey 
{ 
} 

public class PrimaryGuidKey(Guid key) : IPrimaryKey 

public class PrimaryIntegerKey(int key) : IPrimaryKey 

private static OurCustomObject<T>(T identifier) where T : IPrimaryKey