2010-08-23 14 views
11

Deseo crear una propiedad en C# que establezca o devuelva un miembro individual de una matriz. Actualmente, tengo esto:Propiedades que exponen elementos de matriz en C#

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

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

Sin embargo, me sale el siguiente error de compilación:

Bad array declarator: To declare a managed array the rank specifier precedes the variable's identifier. To declare a fixed size buffer field, use the fixed keyword before the field type.

+0

http://www.codeproject.com/KB/cs/csharptips.aspx –

Respuesta

12

Qué tal esto: escriba una clase que haga una cosa y una sola cosa: proporcione acceso aleatorio a los elementos de alguna colección indexada subyacente. Dé esta clase a this indexer.

Para las propiedades a las que desee proporcionar acceso aleatorio, simplemente devuelva una instancia de esta clase de indizador.

aplicación Trivial:

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

Refactoring en su código:

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

Esto le permitirá tener tantas propiedades indexado como desee, sin necesidad de exponer esas propiedades con la interfaz IList<T> .

5

Debe utilizar this como el nombre de la propiedad para los indexadores.

+0

¿Qué pasa si tengo más de uno? –

+0

Tendrá que hacer que MyProperty devuelva algún tipo de lista indexable. Si necesita un control estricto, es posible que desee implementarlo usted mismo. – recursive

0

Necesita usar un indexador. Funciona un poco diferente. Ver ejemplo:

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

Nota: Solo se permite un indexador por clase. La razón es que es demasiado confuso para el compilador como para el significado, por lo que solo se te permite uno.

También puede hacer esto:

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... 
5

C# permite sólo una propiedad indexada por clase, por lo que están obligados a utilizar esto.

+0

eso no es verdad. Puede tener más de un indexador siempre que la firma sea diferente, es decir, el tipo de lo que se utiliza como valor de índice es diferente. –

+0

Las cosas han cambiado entonces. Inicialmente tal limitación existió. ¿Le importaría publicar una nueva sintaxis y decirnos cuándo se agregó al idioma? – joekoyote

+0

tal vez estamos hablando de propósitos cruzados: puede declarar 'public int this [string index]' junto a 'public int this [int index]' y pueden hacer dos cosas completamente diferentes. Yo diría que es más de una propiedad indexada. –

1

Una opción es volver a codificar de la siguiente manera:

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

Se va a compilar, pero tiene su propio conjunto de problemas (FXCop va a gritar sobre ello, pero puede dar lugar a otras opciones) .

+0

Esto es más fuerte que la interfaz original, que solo permite la modificación de los elementos. Esto realmente permite el reemplazo de la matriz subyacente a través del conjunto. –

1

Se podría hacer algo como esto:

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

Usted puede usarlo de esta manera:

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

     set 
     { 
      myProp = value; 
     } 
    } 

Y es posible acces myProp [1] como MyProp [1] para el Ejemplo

2

Exponer su matriz a través de una propiedad de solo lectura podría cubrir sus necesidades.Dado que usted no desea permitir que otro código para asignar la matriz como tal, no hay necesidad de un regulador público:

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

     return myProperty; 
    } 
} 

Entonces se puede escribir código como tal:

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

.. Pero usted no puede sustituir a la matriz en sí:

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

en primer lugar, en el campo de la declaración evita el exceso de verificación:

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

Puede implementar varios controladores paso a paso a través de la sobrecarga por tipo de entrada:

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

C# proporciona ningún mecanismo incorporado para crear propiedades indizadas. Puede usar un indexador de nivel de clase (usando la notación this[int index]), pero nada como esto en un nivel de propiedad.

Una opción es crear una clase auxiliar con un indexador y usar esta clase como el tipo de propiedad. Vea un example en MSDN.

Cuestiones relacionadas