索引切换语句,或等效?.net,C#

Bra*_*itz 6 c# dictionary switch-statement

我想构建一个接受字符串参数的方法,以及一个我想根据参数返回特定成员的对象.所以,最简单的方法是构建一个switch语句:

public GetMemberByName(MyObject myobj, string name)
{
   switch(name){
     case "PropOne": return myobj.prop1;
     case "PropTwo": return myobj.prop2; 
   }
}
Run Code Online (Sandbox Code Playgroud)

这样可以正常工作,但我最终可能会找到一个相当大的列表...所以我很好奇是否有一种方法,没有编写一堆嵌套的if-else结构,以索引方式实现这一点,以便匹配字段通过索引找到而不是通过开关掉落直到找到匹配.

我考虑使用a Dictionary<string, something>来快速访问匹配的字符串(作为关键成员),但由于我想访问传入对象的成员,我不确定如何实现.

  • 我特意试图避免反射等,以便实现非常快速.我可能会使用代码生成,所以解决方案不需要小/紧等.

  • 我最初正在构建一个字典,但每个对象都在初始化它.所以我开始将它移动到一个方法,可以根据键 - 一个switch语句查找值.但由于我不再编入索引,我担心调用此方法的连续查找会很慢.

  • SO:我正在寻找一种方法来结合索引/散列查找(如字典使用)的性能与返回传入对象的特定属性.我可能会将它放在用于它的每个类中的静态方法中.

Jus*_*ner 8

这是一个可以适用于任何类的快速模型(使用反射而不是switch语句):

public static object GetMemberByName<T>(T obj, string name)
{
    PropertyInfo prop = typeof(T).GetProperty(name);
    if(prop != null)
        return prop.GetValue(obj, null);

    throw new ArgumentException("Named property doesn't exist.");
}
Run Code Online (Sandbox Code Playgroud)

或者扩展方法版本(它仍适用于任何对象类型):

public static object GetMemberByName<T>(this T obj, string name)
{
    PropertyInfo prop = typeof(T).GetProperty(name);
    if(prop != null)
        return prop.GetValue(obj, null);

    throw new ArgumentException("Named property doesn't exist.");
}
Run Code Online (Sandbox Code Playgroud)

显然,你可能想要做一些额外的错误检查,但这将是一个开始.

我还从方法中返回了类型对象,原因很简单.这允许调用者处理他们认为合适的值(如果他们需要完全投射).


Jef*_*dge 7

这是一种可以使用字典的简单方法:

    Dictionary<string, Func<MyObject, object>> propertyNameAssociations;

    private void BuildPropertyNameAssociations()
    {
        propertyNameAssociations = new Dictionary<string, Func<MyObject, object>>();
        propertyNameAssociations.Add("PropOne", x => x.prop1);
        propertyNameAssociations.Add("PropTwo", x => x.prop2);
    }

    public object GetMemberByName(MyObject myobj, string name)
    {
        if (propertyNameAssociations.Contains(name))
            return propertyNameAssociations[name](myobj);
        else
            return null;
    }
Run Code Online (Sandbox Code Playgroud)


Bri*_*eon 5

您可以尝试一些选项.

选项1:让对象动态存储属性值.

public GetMemberByName(MyObject myobj, string name)  
{  
  return myobj.GetProperty(name);
}

public class MyObject
{
    private Dictionary<string, object> m_Properties = new Dictionary<string, object>();

    public object GetProperty(string name)
    {
        return m_Properties[name];
    }

    public void SetProperty(string name, object value)
    {
        m_Properties[name] = value;
    }

    public object Prop1
    {
        get { return GetProperty("PropOne"); }
        set { SetProperty("PropOne", value); }
    }

    public object Prop2
    {
        get { return GetProperty("PropTwo"); }
        set { SetProperty("PropTwo", value); }
    }
}
Run Code Online (Sandbox Code Playgroud)

选项2:使用反射.

public GetMemberByName(MyObject myobj, string name)  
{  
    return typeof(MyObject).GetProperty(name).GetValue(obj, null);
}
Run Code Online (Sandbox Code Playgroud)

选项3:保持原样.

这是一个合理的选择,因为Dictionary一旦数字case语句达到某个阈值,字符串数据类型的switch语句将转换为查找.C#3.0编译器的阈值为7.因此,无论有多少个案例陈述,查找都将是O(1).它不会扫描每一个.