【发布时间】:2010-06-04 18:26:40
【问题描述】:
我正在尝试实现一个类来访问不同类型的项目,以类似于数据库行的方式。
但是,我有两种不同的想法,不知道该选择哪一种:
设计 1
public enum ObjectTypeA
{
Undefined,
Integer,
Float
}
public class MyObjectA
{
private object val;
public ObjectTypeA Type
{
get;
private set;
}
public int Integer
{
get
{
if (Type != ObjectTypeA.Integer) throw new Exception();
return (int)val;
}
set
{
Type = ObjectTypeA.Integer;
val = value;
}
}
public float Float
{
get
{
if (Type != ObjectTypeA.Float) throw new Exception();
return (float)val;
}
set
{
Type = ObjectTypeA.Float;
val = value;
}
}
}
- 可能的编译时检查更少。
- 不能使用 is 运算符、GetType() 等(重新发明类型系统)。
- 值类型的装箱和拆箱。
- 可以被其他类继承(例如,我可以使用继承创建一个“命名对象”)。
设计 2
public abstract class MyObjectB
{
}
public class MyIntegerB : MyObjectB
{
public int Value
{
get;
set;
}
public MyIntegerB(int _value)
{
Value = _value;
}
}
public class MyFloatB : MyObjectB
{
public float Value
{
get;
set;
}
public MyFloatB(float _value)
{
Value = _value;
}
}
- 实现更短更简单。
- 使用起来非常冗长(强制转换)。
性能并不重要,但仍然很重要,因为要存储的大多数对象都是整数或浮点数,因此装箱开销很重要。
类将只包含值,而不是依赖于类型等的方法,因此解决方案是否使用继承无关紧要。
重要提示:要求之一是可能有两种类型使用相同的底层类型(例如,从 MyObjectB 派生的两个类可能使用 int 作为值) ,因此可能无法使用 object 或泛型。
关于使用哪种设计或其他不同设计的任何建议?
编辑: 我不喜欢第二个的原因是因为它使用起来非常冗长:
MyObjectB objB = new MyIntegerB(12);
Console.WriteLine(((MyIntegerB)objB).Value);
而且因为我不能继承它来创建类似“命名对象”的东西,所以我必须将MyObjectB附加到该类中,并且用法更加冗长。
【问题讨论】:
-
第一个选项似乎是实现 C 风格联合的糟糕尝试。
-
您这里的要求非常模糊,这使得问题难以回答。这会引发各种危险信号,说明您实际想要完成的工作,以及您认为需要这样做的原因。
-
如果你想支持不止一种类型的对象,只需使用
Nullable<T>并在运行时测试/转换类型就可以了。