C#generics类使用引用类型和可空值类型
我有一个有趣的问题。 我想创建一个可以处理Reference类型和Nullable
类型的generics类。 基本上我想要的东西:
public class ClassWithNull { public T varName = null; }
当然,这当然不会编译,因为并非所有类型都可以赋值为null,即不可为空的值类型。 但问题是Nullable
是一个值类型,所以简单地添加where T : class
对我没有帮助。 我的genericsfoo不是太强,但是我无法找到任何方式来说T
必须是引用类型或可以为值的类型。
我必须解决的想法是使ClassWithNull
成为一个抽象类。 然后我可以添加两个子类,一个用于处理引用类型,另一个用于处理可空值类型。 然后,基类中的静态工厂方法可以使用reflection来确定应该构造哪个子类。 就像是:
public static ClassWithNull CreateClassWithNull() { StackTrace st = new StackTrace(); Type type = st.GetFrame(1).GetMethod().GetGenericArguments()[0]; if (!type.IsValueType) { return new ClassWithReferenceType(); } else if (type == typeof(Nullable)) { return new ClassWithNullableValueType(); } else { throw new Exception("Must provide nullable type."); } }
这里的问题是generics是静态解决的。 如果ClassWithReferenceType
期望U
是引用类型,则在factory方法中调用new ClassWithReferenceType()
是编译错误,因为T
不需要是引用类型。 编译器不知道运行时检查。
关于如何实现这样的事情的任何想法?
怎么样:
public class ClassWithNull { public T varName = default(T); }
(实际上,你甚至不需要赋值 – 你可以将它保留为构造的默认值。但你可能想要局部变量的default(T)
。)
这不会阻止您使用不可为空的值类型错误地使用它 – 但这样就足够了吗?
如果这对你没有帮助,我建议写两个静态方法,如下:
public static ClassWithNull CreateClassWithNullForClass where T : class { return new ClassWithReferenceType (); } public static ClassWithNull CreateClassWithNullForNullable where T : struct { return new ClassWithNullableValueType (); }
ClassWithNullableValueType
的字段将为Nullable
– T
将是基础类型。
现在,如果你想要相同方法的重载,那就更难了,特别是如果你不想传递任何参数。 这是可能的 ,但实际上,真的非常可怕 。
您应该能够这样做:
public class ClassWithNull { private object varName_priv = null; public T varName { get { return (T)varName_priv; } set { varName_priv = value; } } }
这是有效的,因为C#中的每个非指针类型都可以转换为object
,包括值类型。
- c#generic与类型有细微差别?
- 多个可配置的FileSystemWatcher方法
- 在一个带有代码隐藏的ASP.NET网站中,.cs文件是在什么时候编译的?
- 从WPF应用程序中的文本框获取用户输入
- C#:System.Object vs Generics
- 类型’System.Int32’的表达式不能用于方法’Boolean Equals(System.Object)’的’System.Object’类型的参数
- 在WPF中将IsEnabled绑定到IsCheck
- 南希文档中描述的表单身份validation是否容易受到会话劫持的影响?
- 使用MulticastDelegate作为参数,同时避免使用DynamicInvoke