[英]Generic type checking
有沒有辦法強制/限制傳遞給原語的類型? (布爾、整數、字符串等)
現在,我知道您可以通過where子句將泛型類型參數限制為類型或接口實現。 但是,這不符合原語(AFAIK)的要求,因為它們並不都有共同點(除了有人說之前的對象!:P)。
所以,我目前的想法是咬緊牙關,做一個大的switch語句,並在失敗時拋出一個ArgumentException 。
編輯1:
只是為了澄清:
代碼定義應該是這樣的:
public class MyClass<GenericType> ....
和實例化:
MyClass<bool> = new MyClass<bool>(); // Legal
MyClass<string> = new MyClass<string>(); // Legal
MyClass<DataSet> = new MyClass<DataSet>(); // Illegal
MyClass<RobsFunkyHat> = new MyClass<RobsFunkyHat>(); // Illegal (but looks awesome!)
編輯 2
@Jon Limjap - 好點,我已經在考慮了。 我確信有一個通用方法可用於確定該類型是值類型還是引用類型。
這對於立即刪除許多我不想處理的對象很有用(但是您需要擔心使用的結構,例如Size )。 有趣的問題不是嗎? :)
這里是:
where T: struct
取自MSDN 。
我很好奇。 這可以使用擴展方法在 .NET 3.x 中完成嗎? 創建一個接口,並在擴展方法中實現該接口(這可能比有點胖的開關更干凈)。 另外,如果您以后需要擴展到任何輕量級自定義類型,它們也可以實現相同的接口,而無需更改基本代碼。
你們有什么感想?
可悲的消息是我在框架 2 中工作! :D
編輯 3
從Jon Limjaps Pointer開始,這太簡單了。太簡單了,我幾乎想哭,但這很棒,因為代碼就像一個魅力!
所以這就是我所做的(你會笑的!):
bool TypeValid()
{
// Get the TypeCode from the Primitive Type
TypeCode code = Type.GetTypeCode(typeof(PrimitiveDataType));
// All of the TypeCode Enumeration refer Primitive Types
// with the exception of Object and Empty (Null).
// Since I am willing to allow Null Types (at this time)
// all we need to check for is Object!
switch (code)
{
case TypeCode.Object:
return false;
default:
return true;
}
}
然后是一個小工具方法來檢查類型並拋出異常,
private void EnforcePrimitiveType()
{
if (!TypeValid())
throw new InvalidOperationException(
"Unable to Instantiate SimpleMetadata based on the Generic Type of '" + typeof(PrimitiveDataType).Name +
"' - this Class is Designed to Work with Primitive Data Types Only.");
}
然后需要做的就是在類構造函數中調用EnforcePrimitiveType() 。 任務完成! :-)
唯一的缺點是,它只在運行時(顯然)而不是設計時拋出異常。 但這沒什么大不了的,可以使用FxCop之類的實用程序(我們在工作中不使用)。
在此特別感謝 Jon Limjap!
public class Class1<GenericType> where GenericType : struct
{
}
這似乎完成了這項工作..
基元似乎在TypeCode
枚舉中指定:
也許有一種方法可以找出對象是否包含TypeCode enum
,而無需將其強制轉換為特定對象或調用GetType()
或typeof()
?
更新它就在我的眼皮底下。 那里的代碼示例顯示了這一點:
static void WriteObjectInfo(object testObject)
{
TypeCode typeCode = Type.GetTypeCode( testObject.GetType() );
switch( typeCode )
{
case TypeCode.Boolean:
Console.WriteLine("Boolean: {0}", testObject);
break;
case TypeCode.Double:
Console.WriteLine("Double: {0}", testObject);
break;
default:
Console.WriteLine("{0}: {1}", typeCode.ToString(), testObject);
break;
}
}
}
它仍然是一個丑陋的開關。 但這是一個很好的起點!
@Lars 已經說過的差不多了:
//Force T to be a value (primitive) type.
public class Class1<T> where T: struct
//Force T to be a reference type.
public class Class1<T> where T: class
//Force T to be a parameterless constructor.
public class Class1<T> where T: new()
所有工作在 .NET 2、3 和 3.5 中。
如果您可以容忍使用工廠方法(而不是您要求的構造函數 MyClass),您總是可以這樣做:
class MyClass<T>
{
private readonly T _value;
private MyClass(T value) { _value = value; }
public static MyClass<int> FromInt32(int value) { return new MyClass<int>(value); }
public static MyClass<string> FromString(string value) { return new MyClass<string>(value); }
// etc for all the primitive types, or whatever other fixed set of types you are concerned about
}
這里的一個問題是您需要輸入MyClass<AnyTypeItDoesntMatter>.FromInt32
,這很煩人。 如果您想保持構造函數的私有性,則沒有一個很好的解決方法,但這里有一些解決方法:
MyClass
。 使MyClass<T>
繼承自MyClass
並將其嵌套在MyClass
中。 將靜態方法移至MyClass
。 這將解決所有可見性問題,但代價是必須將MyClass<T>
作為MyClass.MyClass<T>
訪問。MyClass<T>
。 創建一個靜態類MyClass
,它使用MyClass<AnyTypeItDoesntMatter>
調用MyClass<T>
中的靜態方法(可能每次都使用適當的類型,只是為了傻笑)。MyClass
,它繼承自MyClass<AnyTypeItDoesntMatter>
。 (具體來說,假設為MyClass<int>
。)因為您可以通過派生類的名稱調用在基類中定義的靜態方法,所以您現在可以使用MyClass.FromString
。這為您提供了靜態檢查,但代價是更多的寫入。
如果您對動態檢查感到滿意,我會在上面的 TypeCode 解決方案中使用一些變體。
遇到類似的挑戰,我想知道你們對IConvertible 界面有何感受。 它允許請求者的要求,並且您可以使用自己的實現進行擴展。
例子:
public class MyClass<TKey>
where TKey : IConvertible
{
// class intentionally abbreviated
}
我認為這是一個解決方案,盡管許多建議也是我選擇的一部分。
但是,我擔心的是,它是否會誤導使用您的課程的潛在開發人員?
干杯-謝謝。
@Rob, Enum
將通過TypeValid
函數,因為它的TypeCode
是Integer
。 我已經更新了函數來檢查Enum
。
Private Function TypeValid() As Boolean
Dim g As Type = GetType(T)
Dim code As TypeCode = Type.GetTypeCode(g)
' All of the TypeCode Enumeration refer Primitive Types
' with the exception of Object and Empty (Nothing).
' Note: must also catch Enum as its type is Integer.
Select Case code
Case TypeCode.Object
Return False
Case Else
' Enum's TypeCode is Integer, so check BaseType
If g.BaseType Is GetType(System.Enum) Then
Return False
Else
Return True
End If
End Select
End Function
您可以使用typeof(PrimitiveDataType).IsPrimitive
屬性來簡化EnforcePrimitiveType
方法。 我錯過了什么嗎?
使用自定義FxCop規則來標記MyClass<>
的不良用法。
在 dotnet 6 中,我在使用struct
時遇到了這個錯誤:
類型“字符串”必須是不可為空的值類型才能將其用作參數“T”
所以我改用 IConvertible
var intClass = new PrimitivesOnly<int>();
var doubleClass = new PrimitivesOnly<double>();
var boolClass = new PrimitivesOnly<bool>();
var stringClass = new PrimitivesOnly<string>();
var myAwesomeClass = new PrimitivesOnly<MyAwesomeClass>(); // illegal
// The line below encounter issue when using "string" type
// class PrimitivesOnly<T> where T : struct
class PrimitivesOnly<T> where T : IConvertible
{
}
class MyAwesomeClass
{
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.