1

我正在尝试制作一个对象来保存一些字符串。对象可以是任何东西,包括集合、数组……字符串必须是可枚举的(IEnumerable 或类似的)。每个字符串索引器都需要被智能感知识别反射是最后一个选项。一个对象,没有单独的索引器对象。

示例用法:

public static class features
{
    public const string favorite = "blue background";
    public const string nice = "animation";
}

public static class Program
{
    public static void Main()
    {
        foreach (string feature in features)
        {
            Console.WriteLine(feature);
        }
        //... select a feature
        Console.WriteLine(features.favorite);
    }
}

编辑: 我将使用 Jim Mischel 提出的第一个解决方案,修改为使用反射,因为这获得了我目前感兴趣的优势。

  • 将所有内容封装在一个实体中
  • 名称直接与值相关联
  • 枚举器是动态的

    public IEnumerator<string> GetEnumerator()
    {
        FieldInfo[] strings = this.GetType().GetFields();
        foreach (FieldInfo currentField in strings)
        {
            yield return currentField.GetValue(null).ToString();
        }
        yield break;
    }
    

我感谢大家的努力。

4

3 回答 3

2

顺便说一句,我可以想到两种方法来做到这一点。但是,既然它必须是IEnumerable<string>它就不能是一个静态类,因为静态类不能实现接口。静态方法也不能实现接口方法。

第一种方法使用常量和一个按顺序返回它们的枚举器:

public class Features: IEnumerable<string>
{
    public const string Favorite = "blue background";
    public const string Nice = "animation";


    public IEnumerator<string> GetEnumerator()
    {
        yield return Favorite;
        yield return Nice;
    }

    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }
}

第二种方法将值存储在数组中并使用 anenum作为索引。枚举器只返回数组的枚举器。同样,这不是静态的,因为枚举器,也因为索引器不能是静态的。

public enum FeaturesIndex
{
    Favorite = 0,
    Nice = 1
}

public class Features2 : IEnumerable<string>
{
    private static readonly string[] _features = new string[]
        {
            "blue background",
            "animation"
        };

    public string this [FeaturesIndex ix]
    {
        get { return _features[(int) ix]; }
    }

    public IEnumerator<string> GetEnumerator()
    {
        return ((IEnumerable<string>) _features).GetEnumerator();
    }

    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }
}

正如其他人所指出的,第三种可能性是使用字典和枚举或定义的常量作为键。这是一种有趣的方法,唯一的潜在缺点是您无法保证枚举集合时返回键的顺序。如果这是一个问题,您可以让您的枚举器在返回之前对序列进行排序。

无论你怎么看,都有权衡取舍。我的两个解决方案都需要手动同步键和值。首先,您必须确保枚举器返回所有值。其次,你必须确保你的enum匹配数组。

选择你的毒药。

这也取决于你将如何使用这个东西。我的第一个解决方案具有简单的优点,如果它是一次写入、永久使用的东西,它可能是完全可以接受的。第二个选项的好处是使用索引器,它更常与集合相关联。

于 2013-07-02T19:16:08.810 回答
0

有很多更好的方法可以做到这一点。要遵循与您正在寻找的类似模式,这是一种方法:

public static class features
{
    public enum TYPES { favorite, nice }
    public static Dictionary<TYPES,string> values = new Dictionary<TYPES,string>() {
         { TYPES.favorite, "blue background" },
         { TYPES.nice, "animation" } };
}

public static class Program
{
    public static void Main()
    {
       foreach (string feature in features.values.keys)
       {
           Console.WriteLine(features.values[feature]);
       }
       //... select a feature
       Console.WriteLine(features.values[TYPES.favorite]);
  }

}

于 2013-07-02T19:11:34.883 回答
0

所以你真正要求的是一个具有属性的对象,你可以更改并且也是可枚举的,但它使你不需要调用反射来枚举,除非绝对必要。

如果我认为您实际上正在寻找的是以下内容

public class Features: IEnumerable<string>
{
    private readonly Dictionary<string,string> _internalCollection;

    public Features()
    {
        _internalCollection = new Dictionary<string,string>();
    }

    private string GetByKey(string id)
    {
        if(!_internalCollection.ContainsKey(id))
            return null;
        return _internalCollection[id];
    }

    private void SetByKey(string id, string value) 
    {
        _internalCollection[id]=value;
    }

    const string _favoriteId = "favorite";
    public string Favorite
    {
         get { return GetByKey(_favoriteId); }
         set { return SetByKey(_favoriteId,value);}
    }

    const string _niceId = "nice";
    public string Nice
    {
         get { return GetByKey(_niceId);}
         set { return SetByKey(_niceId, value);} 
    }

    public string this[string index]
    {
            get { return GetByKey(index.ToLower()); }
            set { return SetByKey(index.ToLower(), value);}  
    }

    public IEnumerator<string> GetEnumerator()
    {
        foreach(var key in _internalCollection.Keys)
            yield return _internalCollection[key];
        yield break;
    }
}
于 2013-07-02T19:56:09.583 回答