【问题标题】:Loop through constant members of a class循环遍历类的常量成员
【发布时间】:2011-06-27 00:56:40
【问题描述】:

我有一个包含常量字符串的类。我想将所有这些字符串放入下拉集合中。做这个的最好方式是什么?这就是我现在所拥有的,理论上,我认为这将是做到这一点的最佳方式。

public class TestClass
{
    private const string _testA = "Test A";
    private const string _testB = "Test B";

    public string TestA
    {
        get { return _testA; }
    }

    public string TestB
    {
        get { return _testB; }
    }
}

public DropDownItemCollection TestCollection
{
    DropDownItemCollection collection = new DropDownItemCollection();
    TestClass class = new TestClass();

    foreach (string testString in class)
    {
        DropDownItem item = new DropDownItem();
        item.Description = testString;
        item.Value = testString;
        collection.Add(item);
    }

    return collection;
}

问题在于这会在 foreach 上返回错误:“...不包含 GetEnumerator 的公共定义。”我尝试创建一个 GetEnumerator,但没有成功,而且我过去没有使用过 GetEnumerator。

非常感谢任何帮助!

【问题讨论】:

    标签: c# class


    【解决方案1】:

    你可以实现一个产生字符串的方法:

    public Ienumerable<string> GetStrings(){
       yield return TestA;
       yield return TestB;
    }
    

    否则,您应该考虑反射以返回静态和字符串属性,然后通过调用它们来获取值。

    问候 GJ

    【讨论】:

    • 什么是_TestA? OP 只有_testA(lowerCase),这是常量本身,而不是它的名字。
    【解决方案2】:

    我也遇到了同样的挑战;获取我的类的所有常量(不是属性!)。基于最流行的答案(对于属性)和约翰的答案(对于常量),我写了这个。我测试了它,它运行良好。

    private List<string> lstOfConstants= new List<string>();
        foreach (var constant in typeof(TestClass).GetFields())
        {
            if (constant.IsLiteral && !constant.IsInitOnly)
            {
                lstOfConstants.Add((string)constant.GetValue(null));
            }
        }
    

    【讨论】:

      【解决方案3】:

      有点晚了,但这不是更好的解决方案吗?

      http://weblogs.asp.net/whaggard/archive/2003/02/20/2708.aspx

      private FieldInfo[] GetConstants(System.Type type)
      {
          ArrayList constants = new ArrayList();
      
          FieldInfo[] fieldInfos = type.GetFields(
              // Gets all public and static fields
      
              BindingFlags.Public | BindingFlags.Static | 
              // This tells it to get the fields from all base types as well
      
              BindingFlags.FlattenHierarchy);
      
          // Go through the list and only pick out the constants
          foreach(FieldInfo fi in fieldInfos)
              // IsLiteral determines if its value is written at 
              //   compile time and not changeable
              // IsInitOnly determine if the field can be set 
              //   in the body of the constructor
              // for C# a field which is readonly keyword would have both true 
              //   but a const field would have only IsLiteral equal to true
              if(fi.IsLiteral && !fi.IsInitOnly)
                  constants.Add(fi);           
      
          // Return an array of FieldInfos
          return (FieldInfo[])constants.ToArray(typeof(FieldInfo));
      }
      

      如果你需要你可以做的名字

      fi.GetValue(null)
      

      在循环内。

      【讨论】:

      • 这给了我奇怪的结果。我声明了一个包含每个内置类型的公共 const 的类,并且这个方法总是忽略小数,由于某种原因 public const decimal Decimal = 1.0m; 有 IsInitOnly = true
      • 看来我并不是第一个注意到这一点的人:codeblog.jonskeet.uk/2014/08/22/…
      【解决方案4】:

      您需要使用反射从自定义类型中获取每个字符串的名称,然后还/可选地获取每个字符串的值...

      类似这样的:

      TestClass theClass = new TestClass();
      
      foreach (PropertyInfo property in theClass.GetType().GetProperties())
      {
      
          Console.WriteLine(property.Name);
          Console.WriteLine(property.GetValue(theClass, null));
      }
      

      【讨论】:

      • 这会得到属性——而不是常量(正如问题所要求的那样)
      【解决方案5】:

      您可以使用反射循环遍历类属性:

      var instance = new TestClass();
      foreach(PropertyInfo pi in typeof(TestClass))
      {
            var val = pi.GetValue(instance,null);
      }
      

      【讨论】:

        【解决方案6】:

        您可以使用反射来遍历所有属性:

        public DropDownItemCollection TestCollection
        {
            var collection = new DropDownItemCollection();
            var instance = new TestClass();
            foreach (var prop in typeof(TestClass).GetProperties())
            {
                if (prop.CanRead)
                {
                    var value = prop.GetValue(instance, null) as string;
                    var item = new DropDownItem();
                    item.Description = value;
                    item.Value = value;
                    collection.Add(item);
                }
            }
            return collection;
        }
        

        【讨论】:

        • 对我来说,这没有返回任何内容(如果返回属性但 const 值不是属性,这似乎是正确的)所以我不知道它是如何获得如此多的支持的。 @John 下面的回答适用于 const 字符串成员。
        • 我和@christutty 有同样的问题,似乎这适用于{ get; set; } 的属性,但似乎不适用于已经具有预定值的属性。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-11-09
        • 2019-07-28
        • 1970-01-01
        • 2012-01-22
        • 2021-12-27
        • 2012-09-12
        相关资源
        最近更新 更多