简体   繁体   English

如何实现一个类来访问C#中几种不同类型的对象?

[英]How to implement a class to access objects of several different types in C#?

I'm trying to implement a class to access items of different types, in a similar way to database rows. 我正在尝试以类似于数据库行的方式实现一个类来访问不同类型的项目。

However, I have two different ideas in mind, and I don't know which one to choose: 但是,我有两个不同的想法,我不知道选择哪一个:

Design 1 设计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;
        }
    }
}
  • Less compile-time checks possible. 可以减少编译时检查。
  • Can't use the is operator, GetType() , etc. (reinvents the type system). 不能使用is运算符, GetType()等(重新发明类型系统)。
  • Boxing and unboxing for value types. 为价值类型装箱和拆箱。
  • Can be inherited by other classes (eg I can create a "named object" using inheritance). 可以由其他类继承(例如,我可以使用继承创建“命名对象”)。

Design 2 设计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;
    }
}
  • Shorter and simpler implementation. 实施更短,更简单。
  • Very verbose (casting) to use. 非常详细(铸造)使用。

Performance is not critical, but it's still important, since most of the objects that are going to be stored are integers or floats, so boxing overhead matters. 性能并不重要,但它仍然很重要,因为大多数要存储的对象都是整数或浮点数,所以拳击开销很重要。

The classes will just contain the values, not methods that depend on the type, etc. so it doesn't matter if the solution uses inheritance. 这些类只包含值,而不是依赖于类型的方法等。因此,如果解决方案使用继承,则无关紧要。

IMPORTANT : One of the requirements is that there may be two types that use the same underlying type (eg two classes derived from MyObjectB may use int as the Value), so using object or generics may not be possible. 重要提示 :其中一个要求是可能有两种类型使用相同的基础类型(例如,从MyObjectB派生的两个类可能使用int作为值),因此使用对象或泛型可能是不可能的。

Any suggestion about which design to use, or another different design? 关于使用哪种设计或其他不同设计的任何建议?

EDIT: The reason I don't like the second one is because it's very verbose to use: 编辑:我不喜欢第二个的原因是因为它使用起来非常冗长:

MyObjectB objB = new MyIntegerB(12);
Console.WriteLine(((MyIntegerB)objB).Value);

And because I can't inherit it to create something like a "named object", so I have to attach MyObjectB to the class, and the usage is even more verbose. 因为我不能继承它来创建类似“命名对象”的东西,所以我必须将MyObjectB附加到类中,并且使用更加冗长。

I don't see why you wouldn't use generics here. 我不明白你为什么不在这里使用泛型。 More strongly: I don't see why you need this at all : It seems like Nullable<T> would cover all of your use cases very nicely. 更强烈:我不明白为什么你需要这个 :这似乎是Nullable<T>将涵盖所有的使用情况非常漂亮。 If not, implementing this generically is trivial: 如果没有,通常实现这一点是微不足道的:

public class ValueWrapper<T>
{
    public T Value
    {
        get;
        private set;
    }

    public Type WrappedType
    {
        get { return typeof(T); }
    }
}

public MySpecialInt : ValueWrapper<int>
{
    /* etc */
}

if you need heterogeneous collections then this would do. 如果您需要异构集合,那么这样做。

public enum ObjectTypeA
{
    Undefined,
    Integer,
    Float
}

public class MyObjectA
{
    public MyObjectA(object value) : this(value, InfereType(value))
    { }

    public MyObjectA(object value, ObjectTypeA type)
    {
        Value = value;
        Type = type;
    }

    public object Value { get; private set; }

    public ObjectTypeA Type
    {
        get;
        private set;
    }

    public T ValueAs<T>()
    {
        return (T)Value;
    }
}

then use it like 那就像使用它一样

List<MyObjectA> list = GetAllValues();
foreach (var item in list)
{
    switch (item.WrappedType)
    {
        case MyObjecttypeA.Float:
            float f = item.ValueAs<float>();
            // do something with float
    }
}

why not use generics? 为什么不使用泛型?

public abstract class MyObjectB<T>
{
    public T Value
    {
        get;
        set;
    }

    public MyObjectB(T _value)
    {
        Value = _value;
    }
}

you only need one class at this point. 此时你只需要一个班级。 just instantiate it differently: 只是以不同的方式实例化它:

var myObj = new MyObjectB<Int>(1);

or 要么

var myObj = new MyObjectB<Float>(0.012);

Have you considered generics? 你考虑过仿制药吗?

public class MyObjectA<T> { 

  public T Value { 
      get; set;
  } 

}

I know you mentioned not wanting to deal with boxing and unboxing, but I still think a Generic class would be your best bet here. 我知道你提到不想处理拳击和拆箱,但我仍然认为Generic类是你最好的选择。

public class MyObject<T>
{
    public MyObject(T t) {
        Value = t;
    }

    public T Value { get; set; }
}

Edit: 编辑:

One of the requirements is that there may be two types that use the same underlying type (eg two classes derived from MyObjectB may use int as the Value), so using object or generics may not be possible. 其中一个要求是可能有两种类型使用相同的基础类型(例如,从MyObjectB派生的两个类可能使用int作为值),因此使用对象或泛型可能是不可能的。

That would only apply if you're extending the class. 这只适用于你扩展课程的情况。 There's no problem if you wrap the class instead, ie create a MyObject<int> and access its Value property, rather than subclassing it. 如果你改为包装类没有问题,即创建一个MyObject<int>并访问它的Value属性,而不是子类化它。

Having said that, if you want to subclass a generic class, the subclass would also need to be a generic class. 话虽如此,如果要子类化泛型类,子类也需要是泛型类。

I've written a similar class that could hold either a single instance of ClassX or an array of ClassX . 我写了一个类似的类,它可容纳任一单个实例ClassX或数组ClassX The trick was that it could change during runtime, so a generic wouldn't suffice, but I still wanted it strong-typed in all cases. 诀窍在于它可能在运行时发生变化,因此通用是不够的,但我仍然希望它在所有情况下都是强类型的。 It sounds like that's similar to what you're trying to accomplish here. 听起来这与你在这里想要完成的事情类似。

I chose the first option, and here's why: Wherever possible, I encapsulate complexity within a class to make the class easier to use. 我选择了第一个选项,这就是原因:只要有可能,我就会在类中封装复杂性,以使类更易于使用。 Classes should encapsulate away complexity from the caller, making calls to it more concise. 类应该封装调用者的复杂性,使调用更简洁。 If using MyObjectB makes your code more verbose, than I don't think that's the right answer. 如果使用MyObjectB使你的代码更加冗长,那么我认为这不是正确的答案。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM