固定容器,可枚举,intellisense可索引(或成员)

时间:2013-07-02 18:56:43

标签: c# arrays

我正在尝试使对象保持一些字符串。对象可以是任何东西,包括集合,数组......字符串需要可枚举(IEnumerable或类似)。每个字符串索引器都需要通过 intellisense 来识别,反射是最后一个选项。一个对象,没有单独的索引器对象。

使用示例:

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;
    }
    

我感谢大家的努力。

3 个答案:

答案 0 :(得分: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();
    }
}

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

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与数组匹配。

选择你的毒药。

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

答案 1 :(得分: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]);
  }

}

答案 2 :(得分: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;
    }
}