通用types检查
有没有办法强制/限制传递给基元的types? (bool,int,string等)
现在,我知道你可以通过where子句将genericstypes参数限制为types或接口实现。 然而,这不符合基本法(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 – 好点,和我已经考虑的东西..我敢肯定有一个通用的方法,可以用来确定types是一个值或引用types..
这可能会立即删除很多我不想处理的对象(但是你需要担心使用的结构,如大小 )有用的..有趣的问题没有? 🙂
这里是:
where T : struct
取自MSDN 。
我很好奇..可以使用扩展方法在.NET 3.x中完成? 创build一个接口,并在扩展方法中实现接口(这可能比一个胖开关更清洁)。 此外,如果您稍后需要扩展到任何轻量级自定义types,则它们也可以实现相同的接口,而不需要对基本代码进行更改。
你们有什么感想?
可悲的消息是我在Framework 2工作! :d
编辑3
从Jon Limjaps指针开始,这个过程非常简单。这么简单,我几乎要哭,但是它很棒,因为代码就像一个魅力!
所以这就是我所做的(你会笑!):
添加到generics类的代码
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; } }
然后用一些实用的方法来检查types并抛出一个exception,
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() 。 任务完成! 🙂
唯一的缺点是,它只是在运行时抛出一个exception(显然),而不是devise时。但这没什么大不了的,可以用像FxCop这样的工具来获取。
特别感谢Jon Limjap对这一个!
看起来在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; } } }
这仍然是一个丑陋的开关。 但是这是一个开始的好地方!
public class Class1<GenericType> where GenericType : struct { }
这个似乎做的工作..
几乎@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 }
这里的一个问题是,你将需要inputMyClass<AnyTypeItDoesntMatter>.FromInt32
,这是烦人的。 如果你想保持构造函数的私有性,这里没有一个很好的解决方法,但是这里有几个解决方法:
- 创build一个抽象类
MyClass
。 使MyClass<T>
从MyClass
inheritance并将其嵌套在MyClass
。 将静态方法移到MyClass
。 这将使所有的可视性工作,代价是必须访问MyClass<T>
MyClass.MyClass<T>
。 - 按给定的方式使用
MyClass<T>
。 创build一个静态类MyClass
,它使用MyClass<AnyTypeItDoesntMatter>
调用MyClass<T>
的静态方法(可能每次都使用相应的types,只是为了咯咯笑)。 - (更容易,但肯定怪异的) 从
MyClass<AnyTypeItDoesntMatter>
inheritance的抽象typesMyClass<AnyTypeItDoesntMatter>
。 (具体来说,让我们说MyClass<int>
。)因为你可以通过派生类的名称调用基类中定义的静态方法,现在可以使用MyClass.FromString
。
这会让你静态检查,而牺牲更多的写作。
如果您对dynamic检查感到满意,我会在上面的TypeCode解决scheme上使用一些变体。
@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<>
不良使用。
有一个类似的挑战,我想知道你们如何看待IConvertible接口 。 它允许请求者需要什么,并且可以使用自己的实现进行扩展。
例:
public class MyClass<TKey> where TKey : IConvertible { // class intentionally abbreviated }
我想这是一个解决scheme,尽pipe许多build议也是我select的一部分。
然而,我担心的是,潜在的开发者使用你的课程是否会产生误导?
干杯 – 谢谢。