【问题标题】:C# class indexer setting dictionary not propertyC# 类索引器设置字典不是属性
【发布时间】:2013-01-19 01:46:33
【问题描述】:

我正在尝试为 C# 类实现字符串索引器,但是当您设置属性时,会设置字典而不是属性。这可能是我缺少的一些简单的东西,我只是看不到它。

objFiveProp temp = new objFiveProp();
temp["index1"] = 3;

将 temp._items["index1"].value 设置为 3。

类:

public class objFiveProp
{

    #region Properties
    private Dictionary<string, int> _items;
    public int this[string key]
    {
        get { return _items[key]; }
        set { _items[key] = value; }
    }

    public int index1 { get; set; }
    public int index2 { get; set; }
    public int index3 { get; set; }
    public int index4 { get; set; }
    public int index5 { get; set; }

    #endregion
    #region Constructor

    public objFiveProp()
    {
        index1 = 0;
        index2 = 0;
        index3 = 0;
        index4 = 0;
        index5 = 0;
        _items = new Dictionary<string, int>();
        _items.Add("index1", index1);
        _items.Add("index2", index2);
        _items.Add("index3", index3);
        _items.Add("index4", index4);
        _items.Add("index5", index5);

    }

    #endregion

}

【问题讨论】:

    标签: c# asp.net-mvc


    【解决方案1】:

    这就是它的工作原理。 Dictionary 包含您用来设置它的整数的副本 - 不是对属性的引用。

    我会通过以下方式解决这个问题:

    public class objFiveProp
    {
        private Dictionary<string, int> _items;
        public int this[string key]
        {
            get { return _items[key]; }
            set { _items[key] = value; }
        }
    
        public int Index1 
        {
            get { return this["index1"]; } 
            set { this["index1"] = value; }
        }
        public int Index2
        {
            get { return this["index2"]; } 
            set { this["index2"] = value; }
        }
    
        // ....
    
        public objFiveProp()
        {
            _items = new Dictionary<string, int>();
            _items.Add("index1", index1);
            _items.Add("index2", index2);
            _items.Add("index3", index3);
            _items.Add("index4", index4);
            _items.Add("index5", index5);    
        }
    
    #endregion
    

    这会导致您的属性始终提取存储在字典中的值并保存在那里,因此不会有两个值的副本。

    【讨论】:

      【解决方案2】:

      这是因为在索引设置方法中,您正在设置字典项的值

      public int this[string key]
          {
              get { return _items[key]; } 
              set { _items[key] = value; } //here you are setting the value of dictionary item not the property
          }
      

      要么为 index1、index2 等创建单独的属性,要么在上面的 set 方法中添加检查,虽然是一个肮脏的解决方案,根据 key 的值设置成员变量的值;比如:

      set {  
         _items[key] = value; 
         if(key == "index1")
               index1 = value;
      }
      

      【讨论】:

        【解决方案3】:

        int 是值类型,而不是引用类型。当您在 _items 中设置值时,它不会设置属性,即使您最初是从属性中添加的。

        来自MSDN

        基于值类型的变量直接包含值。 将一个值类型变量分配给另一个会复制所包含的 价值。这与引用类型变量的赋值不同, 它复制对对象的引用,而不是对象本身。

        如果您确实需要能够从索引器和属性访问您的数据,最简单的方法之一就是这样重写您的属性:

        public int indexN
        {
            get { return _items["indexN"]; }
            set { _items["indexN"] = value; }
        }
        

        另一种方法是在索引器的设置器中使用反射:

        public int this[string key]
        {
            get { return _items[key]; }
            set 
            { 
                _items[key] = value; 
                PropertyInfo prop = this.GetType().GetProperty(key);
                if (prop != null)
                {
                    prop.SetValue(this, null);
                }
            }
        }
        

        请记住,反射相对非常简单

        还有其他方法可以完成您正在尝试做的事情,但也许最好的解决方案是根本不这样做。为你的类选择最好的接口,无论是索引器还是属性,并坚持下去。您的代码将更易于维护(您不必维护类数据的两个公共接口)并且更具可读性(其他编码人员不需要知道索引器和属性是相同的)。干杯!

        【讨论】:

          猜你喜欢
          • 2019-09-15
          • 2018-03-14
          • 1970-01-01
          • 2018-11-20
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-06-13
          • 1970-01-01
          相关资源
          最近更新 更多