有没有办法强制/限制传递给基元的类型? (bool,int,string等)
现在,我知道您可以通过 where 子句将泛型类型参数限制为类型或接口实现。然而,这不符合基元(AFAIK)的费用,因为它们并非都有共同点(除了对象之后才有人说!:P)。
所以,我目前的想法只是咬紧牙关并做一个大的开关语句并在失败时抛出 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中完成吗?创建一个接口,并在扩展方法中实现接口(这可能比胖胖的开关更干净)。此外,如果您稍后需要扩展到任何轻量级自定义类型,它们也可以实现相同的接口,而不需要对基本代码进行任何更改。
你们有什么想法?
可悲的消息是我在Framework 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关于这个!
答案 0 :(得分:73)
public class Class1<GenericType> where GenericType : struct
{
}
这个似乎做了这个工作..
答案 1 :(得分:39)
基元似乎在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;
}
}
}
这仍然是一个丑陋的开关。但这是一个开始的好地方!
答案 2 :(得分:21)
几乎@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中完成。
答案 3 :(得分:4)
如果您可以容忍使用工厂方法(而不是您要求的构造函数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<T>
,使用MyClass<AnyTypeItDoesntMatter>
调用MyClass
中的静态方法(每次可能使用适当的类型,只是为了咯咯笑)。MyClass<AnyTypeItDoesntMatter>
的抽象类型MyClass<int>
。 (具体来说,让我们说MyClass.FromString
。)因为您可以通过派生类的名称调用基类中定义的静态方法,所以现在可以使用{{1}}。这会以更多的写作为代价进行静态检查。
如果您对动态检查感到满意,我会在上面的TypeCode解决方案中使用一些变体。
答案 4 :(得分:3)
@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
答案 5 :(得分:2)
使用自定义FxCop规则来标记MyClass<>
的不良用法。
答案 6 :(得分:2)
您可以使用typeof(PrimitiveDataType).IsPrimitive
属性简化EnforcePrimitiveType
方法。我错过了什么吗?