【问题标题】:Accessing object member variable values in .net using an enum使用枚举访问 .net 中的对象成员变量值
【发布时间】:2012-06-18 15:37:36
【问题描述】:

[编辑删除我需要访问 .net 属性(副成员变量)的暗示]

我正在尝试使用 .net(具体来说是用 C# 编码的 WPF)创建一个设计模式,其中类的实例(从基类派生)具有可以通过传递枚举值来访问的成员变量一个方法调用。例如myObject.GetValueOf(dimensionFields.Latitude) 将返回 myObject 持有的“纬度”值。显然,其目的是在运行时使用GetValueOf([some enum variable]) 来访问由枚举定义的许多字段值中的任何一个。我还需要相当高的性能,因为当许多(可能很容易超过 100,000 个)对象被绘制到显示器(通过 OpenGL)时,将访问这些值。

由于性能要求,我不愿意使用反射——这是一个合理的不情愿吗?

我有一个解决方案,但我的问题是:“他们是更好或更简单的方法吗?”

这是我当前的解决方案:我将为我想要访问的每种类型的成员变量创建枚举(即,一种用于双精度数,一种用于整数,一种用于字符串,一种用于布尔值等)。我的对象的基类将具有对应于每种变量类型的字典(例如,Dictionary<FieldsForDoubles, double> m_doubleDict)。该基类中的 GetValueOf([some enum value]) 方法将被重载以接受每种类型的枚举并返回适当的数据类型(例如,public double GetValueOf(FieldsForDoubles field))。为方便起见,派生类可以添加实际属性(例如,Latitude 属性),但这些属性只会访问相应的字典。

最后,作为一次短途旅行,我可能会通过字符串值而不是枚举值来访问字典,让GetValueOf 方法使用someEnumValue.ToString() 访问字典并提供一个通用方法(GetVaueOf<type>(string variableName))来允许某些派生类保存不在当前枚举中但可以通过非常相似的模式访问的变量(例如,我可以使用 GetValueOf<double>([some variable name]) 访问任何使用此模式的变量)

任何人都发现这种方法存在问题(例如,访问相当短的字典不是那种费用,对吧?)?关于如何做到这一点还有其他想法吗?

提前致谢。

【问题讨论】:

  • 为什么不将所有内容都保存在字典中并使用枚举作为键呢?是否有令人信服的理由证明存在属性?
  • 我认为我的标题和描述可能具有误导性。我所说的“属性”实际上只是指类持有的任何变量。如上所述,我目前的想法是按照您的建议使用字典。如果需要,任何相关属性都将由派生类添加以方便访问。
  • 所以你想重新发明它而不是使用反射?我不知道反射和使用字典存储值之间的性能差异,但我无法想象会有很大的差距。如果它那么快,那么 .NET 不会在后端这样做吗?

标签: .net reflection properties


【解决方案1】:

如果我离开了,请告诉我,我会删除。为什么数据需要是属性、枚举和字典?为什么不只是 vcsjones 评论中的字典?您从属性开始,然后参考字段“字段值的数量”。目前尚不清楚您想要什么。您是否计划在运行时构建枚举和属性 - 如果是,您打算如何做到这一点?

可能的简化方法。

public class dynamicClass
{
    public Dictionary<string, string> DicString { get; private set; }
    public Dictionary<string, Int32>  DicInt32  { get; private set; }

    public string GetStringFromKey(string key) { return DicString[key]; }

我看不出 GetStringFromKey 带来了什么。

在客户端 DicString[key];与 GetStringFromKey(key);

【讨论】:

  • 感谢您的回复。我认为我的标题和描述可能具有误导性。我所说的“属性”实际上只是指类持有的任何变量。你的模式几乎就是我在想的,虽然我会添加一个通用的访问方法,比如GetValueOf([some variable])
  • 那么请编辑您的问题。在 SO 上,大多数人会将属性视为正式的 .NET 属性。我没有看到 GetValueOf 带来了什么?
【解决方案2】:

(首先,没有答案) 就个人而言,我将致力于开发一种方法来解决重新创建反射的需要。直接属性引用总是更快,因为它们保存内存地址。任何类型的重定向或查找总是会更昂贵。

(这是一个答案) 显然我们不知道您的要求或系统,所以这里有一个想法。如果您的属性是在枚举中定义的,那么理论上它们不是在运行时创建的。因此,与其使用字典,不如直接使用数组?如果你有

enum
  prop1 = 0
  prop2 = 1
  prop3 = 2

那么你只需要一个长度为 3 的数组。当用户传递一个枚举时,将它用作数组的索引。

编辑:如果性能是您的主要驱动力,那么您需要为每种类型的变量创建不同的枚举,以便您的数组可以“强”类型化(非对象)。然后,您需要为每种类型使用不同的功能。所以:

enum intProp
  prop1 = 0
  prop2 = 1
  prop3 = 2

enum floatProp
  prop1 = 0
  prop2 = 1
  prop3 = 2

int[] intVals
float[] floatVals

fun int getIntProp(intProp p)
  return intVals[(int)p]

fun float getFloatProp(floatProp p)
  return floatVals[(int)p]

它并不漂亮,但它应该足够快以处理 100,000 个对象。不幸的是,我们必须经常平衡性能和可维护性。这是丑陋的代码,但漂亮整洁的代码几乎总是会对性能产生影响。

如果您想要真正的闪电性能,最好的办法是使用 C++ 并直接管理地址。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-06-04
    • 2016-03-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多