【问题标题】:avoid manipulation of element of List避免操作 List 的元素
【发布时间】:2014-06-06 03:58:45
【问题描述】:

我是 WPF 的新手,遵循 mvvm 模式。

我定义了两个类, int class abc,我不想改变_xyz所以我定义了只读,它只能通过abc的构造函数设置一次

class xyz
{
   private int _x;
   public int X
{
   get { return _x ;}
   public xyz(int xvalue) { this.X = xvalue; }
}

class abc
{
    public abc(List<xyz> listXyz)
      {
          _xyz = new List<xyz>(listXyz);
      }

    private readonly List<xyz> _xyz;
        public List<xyz> XYZ
        {
            get
            {
                return _xyz;
            }
        }
}

但如果我通过以下方式实现它,

其中操纵里面的任何元素,因为我已经将它作为接口公开了

var model = new abc(....);

model.XYZ.Add(new xyz()); 模型.XYZ.Clear();

现在我的问题是如何限制 XYZ 以下列方式操作?我不想通过下面的方式改变它,它应该只由 abc 的构造函数分配一次。

【问题讨论】:

    标签: c# wpf list interface


    【解决方案1】:

    您好,您可以考虑扩展 IList,这将允许您创建一个只读列表,该列表应该可以解决与其他方法相关的所有问题。这是我刚刚编写的代码,它实现了我正在谈论的内容。 注意:当列表为只读时,会抛出自定义异常;如果你愿意,你可以删除它。

    public class CustomList<T> : IList<T>
    {
        private IList<T> _list;
        private Boolean _isReadOnly;
    
        public CustomList(IList<T> source, Boolean isReadOnly)
        {
            _list = source;
            _isReadOnly = isReadOnly;
        }
    
        public int IndexOf(T item)
        {
            return _list.IndexOf(item);
        }
    
        public void Insert(int index, T item)
        {
            if (_isReadOnly == true)
            {
                throw new Exception("List is readonly. Method = Insert(int index, T item)");
            }
            _list.Insert(index, item);
        }
    
        public void RemoveAt(int index)
        {
            if (_isReadOnly == true)
            {
                throw new Exception("List is readonly. Method = RemoveAt(int index)");
            }
            _list.RemoveAt(index);
        }
    
        public T this[int index]
        {
            get
            {
                return _list[index];
            }
            set
            {
                if (_isReadOnly == true)
                {
                    throw new Exception("List is readonly. Property = this[int index]");
                }
                _list[index] = value;
            }
        }
    
        public void Add(T item)
        {
            if (_isReadOnly == true)
            {
                throw new Exception("List is readonly. Method = Add(T item)");
            }
            _list.Add(item);
        }
    
        public void Clear()
        {
            if (_isReadOnly == true)
            {
                throw new Exception("List is readonly. Method = Clear()");
            }
            _list.Clear();
        }
    
        public bool Contains(T item)
        {
            return _list.Contains(item);
        }
    
        public void CopyTo(T[] array, int arrayIndex)
        {
            _list.CopyTo(array, arrayIndex);
        }
    
        public int Count
        {
            get { return _list.Count; }
        }
    
        public bool IsReadOnly
        {
            get { return _isReadOnly; }
        }
    
        public bool Remove(T item)
        {
            if (_isReadOnly == true)
            {
                throw new Exception("List is readonly. Method = Remove(T item)");
            }
            return _list.Remove(item);
        }
    
        public IEnumerator<T> GetEnumerator()
        {
            return _list.GetEnumerator();
        }
    
        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return _list.GetEnumerator();
        }
    }
    

    【讨论】:

      【解决方案2】:

      您不能修改列表的行为(所以是的,虽然您可以阻止列表本身的分配,但您不能阻止某人使用它的方法)。

      您可以做的就是不通过简单地提供一个 IEnumerable 来公开列表。

      天真的方法是

      private readonly IEnumerable<xyz> _xyz;
          public List<xyz> XYZ
          {
              get
              {
                  return _xyz;
              }
          }
      

      但是这不会起作用,因为调用者可以简单地将其转换回原样

      ((List<xyz>)myabc).Add(whatever)
      

      你可以做的是根本不返回列表,而是使用 yield 关键字让数据流式传输(与 foreach 兼容)而不返回支持类:

      private readonly IEnumerable<xyz> _xyz;
          public IEnumerable<xyz> XYZ
          {
              get
              {
                  foreach(var item in _xyz)
                  {
                      yield return item; // Every time will get returned 1 by 1 as the caller énumérâtes this, no list is ever returned
                  }
              }
          }
      

      【讨论】:

        【解决方案3】:

        如果您将集合公开为列表,则无法对其进行限制。而是将您的集合公开为 IEnumerable

            public IEnumerable<xyz> XYZ
            {
                get
                {
                    return _xyz.AsEnumerable();;
                }
            }
        

        【讨论】:

          猜你喜欢
          • 2011-06-13
          • 2014-04-17
          • 1970-01-01
          • 2021-11-22
          • 2020-01-24
          • 2020-11-01
          • 1970-01-01
          • 1970-01-01
          • 2012-09-25
          相关资源
          最近更新 更多