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

本文关键字:成员 索引 枚举 intellisense | 更新日期: 2023-09-27 18:20:49

我正在尝试创建一个对象来容纳一些字符串。对象可以是任何东西,包括集合、数组。。。字符串需要是可枚举的(IEnumerable或类似)。每个字符串索引器都需要intellisense知道,Reflection是最后一个选项。一个单独的对象,索引器没有单独的对象。

示例用法:

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

我感谢大家的努力。

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

我可以想出两种方法。但是,由于它必须是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与数组匹配。

拿起你的毒药。

这也取决于你将如何使用这个东西。我的第一个解决方案具有简单性的优点,如果它是一种写一次,永远使用的东西,可能会很容易被接受。第二个选项的好处是使用索引器,它通常与集合相关联。

有很多更好的方法可以做到这一点。为了遵循与你所寻找的相似的模式,这里有一种方法:

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

}

因此,您真正想要的是一个具有属性的对象,您可以更改该对象,该对象也是可枚举的,但它使您不需要调用反射来枚举,除非绝对必要。

如果我认为你实际看到的是以下

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