【问题标题】:Properties exposing array elements in C#在 C# 中公开数组元素的属性
【发布时间】:2011-04-02 15:24:37
【问题描述】:

我想在 C# 中创建一个属性,用于设置或返回数组的单个成员。目前,我有这个:

private string[] myProperty;
public string MyProperty[int idx]
{
    get
    {
        if (myProperty == null)
            myProperty = new String[2];

        return myProperty[idx];
    }
    set
    {
        myProperty[idx] = value;
    }
}

但是,我得到以下编译错误:

错误的数组声明符:要声明托管数组,排名说明符位于变量标识符之前。要声明一个固定大小的缓冲区字段,请在字段类型前使用 fixed 关键字。

【问题讨论】:

标签: c# arrays properties


【解决方案1】:

如何:编写一个只做一件事且只做一件事的类:提供对某些底层索引集合的元素的随机访问。给 this 类一个 this 索引器。

对于您要提供随机访问的属性,只需返回此索引器类的实例即可。

简单的实现:

public class Indexer<T>
{
    private IList<T> _source;

    public Indexer(IList<T> source)
    {
        _source = source;
    }

    public T this[int index]
    {
        get { return _source[index]; }
        set { _source[index] = value; }
    }
}

public static class IndexHelper
{
    public static Indexer<T> GetIndexer<T>(this IList<T> indexedCollection)
    {
        // could cache this result for a performance improvement,
        // if appropriate
        return new Indexer<T>(indexedCollection);
    }
}

重构代码:

private string[] myProperty;
public Indexer<string> MyProperty
{
    get
    {
        return myProperty.GetIndexer();
    }
}

这将允许您拥有任意数量的索引属性,而无需使用IList&lt;T&gt; 接口公开这些属性。

【讨论】:

    【解决方案2】:

    您必须使用this 作为索引器的属性名称。

    【讨论】:

    • 如果我有多个怎么办?
    • 您必须让 MyProperty 返回某种可索引列表。如果您需要严格控制,您可能需要自己实施。
    【解决方案3】:

    C# 只允许每个类有一个索引属性,所以你不得不使用它。

    【讨论】:

    • 这不是真的。只要签名不同,即用作索引值的类型不同,您就可以拥有多个索引器。
    • 事情发生了变化。最初确实存在这种限制。您介意发布新语法并告诉我们它是什么时候添加到语言中的吗?
    • 也许我们在谈论不同的目的:您可以在 public int this[int index] 旁边声明 public int this[string index],他们可以做两件完全不同的事情。我会说这不仅仅是一个索引属性。
    • 知道了。从类设计器的角度来看,您仍然拥有一个属性,因为它只有一个名称。想象一下 StringList 类,在其他语言中它可能具有属性 Strings[int]、Objects[string key]、Names[int]、Values[string name] 等。在 C# 中你无法实现它们,即使你可以,它也不是明显且几乎无法使用。
    【解决方案4】:

    你可以这样使用它:

        private string[] myProp;
        public string[] MyProp
        {
            get
            {
                if (myProp == null)
                {
                    myProp = new String[2];
                }
                return myProp;
            }
    
            set
            {
                myProp = value;
            }
        }
    

    例如,可以将 myProp[1] 作为 MyProp[1] 访问

    【讨论】:

      【解决方案5】:

      通过只读属性公开您的数组可能会满足您的需求。由于您不想让其他代码这样分配数组,因此不需要公共 setter:

      private string[] myProperty;
      public string[] MyProperty
      {
          get
          {
              if (myProperty == null)
              {
                  myProperty = new String[2];
              }
      
              return myProperty;
          }  
      }
      

      然后你可以这样写代码:

      theObject.MyProperty[1] = "some string";
      

      ...但是您不能替换数组本身:

      theObject.MyProperty = new string[2]; // will not compile
      

      【讨论】:

        【解决方案6】:

        一种选择是将其重新编码如下:

        private string[] myProperty = new string[2]; 
        public string[] MyProperty
        { 
            get 
            { 
                return myProperty;
            } 
            set 
            { 
                myProperty = value; 
            } 
        } 
        

        它会编译,但它确实有自己的一系列问题(fxCop 会大喊大叫,但它可以引导您选择其他选项)。

        【讨论】:

        • 这比原来的界面更强大,只允许修改元素。这实际上允许通过 set 替换底层数组。
        【解决方案7】:

        你可以这样做:

        class Indexers
        {
            private string[] _strings = new [] {"A","B"};
            private int[] _ints = new[] { 1, 2 };
        
            public string[] Strings
            {
                get{ return _strings;}
            }
        
            public int[] Ints
            {
                get{ return _ints;}
            }
        }
        
        class Program
        {
            static void Main(string[] args)
            {
                Indexers indexers = new Indexers();
        
                int a1 = indexers.Ints[0];
                string a2 = indexers.Strings[0];
            }
        }
        

        【讨论】:

          【解决方案8】:

          C# 没有提供创建索引属性的内置机制。您可以使用类级别的索引器(使用this[int index] 表示法),但在属性级别上没有这样的东西。

          一种选择是创建一个带有索引器的辅助类,并将该类用作属性类型。请参阅 MSDN 上的 example

          【讨论】:

            【解决方案9】:

            首先,现场声明避免过度检查:

            private string[] myProperty = new string[2];
            

            您可以通过输入类型的重载来实现多个索引器:

            public string this[int index]
            {
                get
                {
                    return myProperty[index];
                }
                set
                {
                    myProperty[index] = value;
                }
            }
            
            public object this[object a, object b] // different input type(s) (and different return type)
            {
                get
                {
                    // do other stuff
                }
            }
            

            【讨论】:

              【解决方案10】:

              您需要使用索引器。它的工作方式略有不同。见例子:

              public class Node
              {
                  public Node this[int offset]
                  {
                      get { return localList[offset]; }
                  }
              }
              

              注意:每个类只能使用一个索引器。原因是编译器对含义的理解太混乱了,所以只允许你一个。

              您也可以这样做:

              private static int[] _widget = new int[Counter];
              public static int [] Widget
              {
                  get { return _widget; }
                  set { _widget = value; }
              }
              

              ...

              for (int i = 0; i <  MyClass.Counter; i++)
              {
                  MyClass.Widget[i] = i;
              }
              
              ...
              double _newWidget5 = MyClass.Widget[5];
              // and so on...
              

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2016-03-24
                • 2020-04-18
                • 2017-05-30
                • 1970-01-01
                • 2016-01-01
                相关资源
                最近更新 更多