具有通用结构的 C# 类设计
这可能是一个简单的问题,但我的头脑拒绝解决这个问题,所以在这种情况下,外部视图总是有用的!
我需要设计一个对象层次结构来为患者实现参数注册。这将在某个日期进行并收集有关患者的许多不同参数(血压、心率等)。这些参数注册的值可以是不同的类型,例如字符串、整数、浮点数甚至 guid(用于查找列表)。
所以我们有:
public class ParameterRegistration
{
public DateTime RegistrationDate { get; set; }
public IList<ParameterRegistrationValue> ParameterRegistrationValues { get; set; }
}
public class ParameterRegistrationValue
{
public Parameter Parameter { get; set; }
public RegistrationValue RegistrationValue { get; set; } // this needs to accomodate the different possible types of registrations!
}
public class Parameter
{
// some general information about Parameters
}
public class RegistrationValue<T>
{
public RegistrationValue(T value)
{
Value = value;
}
public T Value { get; private set; }
}
更新:感谢这些建议,该模型现在已变成以下内容:
public class ParameterRegistration
{
public DateTime RegistrationDate { get; set; }
public IList<ParameterRegistrationValue> ParameterRegistrationValues { get; set; }
}
public abstract class ParameterRegistrationValue()
{
public static ParameterRegistrationValue CreateParameterRegistrationValue(ParameterType type)
{
switch(type)
{
case ParameterType.Integer:
return new ParameterRegistrationValue<Int32>();
case ParameterType.String:
return new ParameterRegistrationValue<String>();
case ParameterType.Guid:
return new ParameterRegistrationValue<Guid>();
default: throw new ArgumentOutOfRangeException("Invalid ParameterType: " + type);
}
}
public Parameter Parameter { get; set; }
}
public class ParameterRegistrationValue<T> : ParameterRegistrationValue
{
public T RegistrationValue {get; set; }
}
public enum ParameterType
{
Integer,
Guid,
String
}
public class Parameter
{
public string ParameterName { get; set; }
public ParameterType ParameterType { get; set;}
}
这确实更简单了一些,但现在我想知道,因为ParameterRegistration 中的 IList 指向抽象 ParameterRegistrationValue 对象,我如何才能获取实际值(因为它存储在子对象上)?
也许整个通用的东西毕竟不是完全正确的方法:s
This might be a simple one, but my head is refusing to wrap around that, so an outside view is always useful in that case!
I need to design an object hierarchy to implement a Parameter Registration for a patient. This will take place on a certain date and collect a number of different parameters about a patient (bloodpressure, heartrate etc). The values of those Parameter Registrations can be of different types, such as strings, integers, floats or even guids (for lookup lists).
So we have:
public class ParameterRegistration
{
public DateTime RegistrationDate { get; set; }
public IList<ParameterRegistrationValue> ParameterRegistrationValues { get; set; }
}
public class ParameterRegistrationValue
{
public Parameter Parameter { get; set; }
public RegistrationValue RegistrationValue { get; set; } // this needs to accomodate the different possible types of registrations!
}
public class Parameter
{
// some general information about Parameters
}
public class RegistrationValue<T>
{
public RegistrationValue(T value)
{
Value = value;
}
public T Value { get; private set; }
}
UPDATE: Thanks to the suggestions, the model has now morphed to the following:
public class ParameterRegistration
{
public DateTime RegistrationDate { get; set; }
public IList<ParameterRegistrationValue> ParameterRegistrationValues { get; set; }
}
public abstract class ParameterRegistrationValue()
{
public static ParameterRegistrationValue CreateParameterRegistrationValue(ParameterType type)
{
switch(type)
{
case ParameterType.Integer:
return new ParameterRegistrationValue<Int32>();
case ParameterType.String:
return new ParameterRegistrationValue<String>();
case ParameterType.Guid:
return new ParameterRegistrationValue<Guid>();
default: throw new ArgumentOutOfRangeException("Invalid ParameterType: " + type);
}
}
public Parameter Parameter { get; set; }
}
public class ParameterRegistrationValue<T> : ParameterRegistrationValue
{
public T RegistrationValue {get; set; }
}
public enum ParameterType
{
Integer,
Guid,
String
}
public class Parameter
{
public string ParameterName { get; set; }
public ParameterType ParameterType { get; set;}
}
which is indeed a bit simpler, but now I'm wondering, since the IList in ParameterRegistration points to the abstract ParameterRegistrationValue object, how will I be able to get the actual value out (since its stored on the sub-objects)?
Maybe the whole generic thing is indeed not quite the way to go after all :s
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
如果您不知道最终的参数集以及每个参数的相应类型,那么泛型可能不会有帮助 - 使用 object 作为参数值类型。
此外,迭代参数列表将很痛苦,因为您必须检查每个项目的类型以确定如何处理该值。
您想通过泛型实现什么目标?是的,它们很酷(装箱/拆箱可能不是最好的主意),但在某些情况下,您可能想使用 object 代替(为了简单性和灵活性)。
——帕维尔
If you don't know the final set of parameter and the corresponding type of each parameter then the generics probably won't help - use object as a parameter value type.
Furthermore iterating through the list of parameters will be a pain since you'll have to examine the type of each item in order to determine how to treat the value.
What are you trying to achieve with generics ? Yes, they are cool (and going for boxing/unboxing is probably not a best idea), but in some cases you might want to use object instead (for both simplicity and flexibility).
-- Pavel
您可能想要引入一个非泛型的
RegistrationValue
抽象基类,以便您的ParameterRegistrationValue
类可以保存非泛型引用,而无需所涉及类型的知识。或者,也可以将ParameterRegistrationValue
设为通用,然后为其添加一个非通用基类(以便ParameterRegistration
中的值列表可以是 第一种方法:
现在您的代码应该可以编译。
一旦您有了非泛型基类,我还将把不依赖于泛型类型参数的泛型类的任何成员移到该基类中。本示例中没有任何内容,但如果我们将 ParameterRegistrationValue 修改为通用的,我会将 Parameter 向上移动到非通用基类中(因为它不依赖于
RegistrationValue
的类型参数)What you might want to introduce is an abstract base class for
RegistrationValue<T>
that is not generic, so that yourParameterRegistrationValue
class can hold a non-generic reference, without needing knowledge of the type involved. Alternatively, it may be appropriate to makeParameterRegistrationValue
generic also, and then add a non-generic base class for it instead (so that the list of values inParameterRegistration
can be of different types.1st way:
And now your code should compile.
Once you have a non-generic base class, I'd also move any members of the generic class that don't depend on the generic type parameters up into this base class. There aren't any in this example, but if we were instead modifying
ParameterRegistrationValue
to be generic, I'd moveParameter
up into the non-generic base class (because it doesn't depend on the type parameter forRegistrationValue
)也许,您应该使用 public RegistrationValue RegistrationValue,其中 T - 是类型,在通用中使用。例如,T - 是字符串或其他类或结构。
或者您应该将 ParameterRegistrationValue 类设置为通用类,以便在 RegistrationValue 字段中使用通用参数。
May be, you should use public RegistrationValue RegistrationValue, where T - is type, using in generic. For example, T - is String or other class or struct.
Or you should make class ParameterRegistrationValue as generic, to use generic argument in the field RegistrationValue.
我相信您希望拥有不同
RegistrationValue
派生类的实例的集合,并且能够对其进行迭代,并且每个元素具有不同的类型。那是相当不可能的事。您仍然需要将每个元素转换为您知道的类型,因为迭代集合将返回对基本类型的引用(
ParameterRegistrationValue
- 这是由IList
指定的)类型参数)。因此,它与迭代非泛型object
列表不会产生任何真正的区别。如果您可以安全地对每个参数进行转换(您知道所有类型),那么您可能根本不需要这样的集合 - 最好有一个类将所有参数封装在一种类型中,所以您可以使用强类型、IntelliSense 等来调用它,如下所示:
I believe you want to have a collection of instances of different
RegistrationValue
s-derived classes and be able to iterate it and for to have different type for each element. That's rather impossible.You'll still need to cast each element to the type you know it is, because iterating the collection will return references to your base type (
ParameterRegistrationValue
- this one specified byIList
type parameter). So it won't make any real difference from iterating over non-genericobject
list.And if you can safely do that casting for each parameter (you know all the types), you probably don't need collection like this at all - it'll be better to have a class that encapsulates all the parameters in one type, so that you can call it with strong types, with IntelliSense etc. like this: