web-dev-qa-db-fra.com

Cas d'utilisation réels pour les indexeurs C #?

J'ai vu beaucoup d'exemples d'indexeurs c #, mais de quelle manière cela m'aidera-t-il dans des situations réelles.

Je sais que le gourou C # n’aurait pas ajouté cela si ce n’était pas une fonctionnalité sérieuse, mais je ne peux pas penser à une situation du monde réel (pas au fool bar) d’utiliser des indexeurs.

Remarque: je me rends compte qu'une question connexe existe, mais elle ne m'aide pas beaucoup.

43
Vivek Bernard

La façon dont je considère les indexeurs est que (à tort ou à raison!), Accéder à quelque chose par index devrait être plus efficace que d’y accéder de toute autre manière, car d’une manière ou d’une autre, la classe dont l’indexeur que je suis utilise stocke quelque de index qui lui permet de rechercher rapidement des valeurs lorsqu’il est accédé de cette façon.

L'exemple classique est un tableau. Lorsque vous accédez à l'élément n d'un tableau en utilisant le code myarray [3], le compilateur/interprète sait quelle est la taille des éléments (du point de vue de la mémoire) du tableau et peut le traiter comme un décalage du début du tableau. Vous pouvez également "for(int i = 0; i < myarray.length; i++) { if (i = 3) then { .. do stuff } }" (ce n’est pas ce que vous voudrez!), Ce qui serait moins efficace. Il montre également comment un tableau est un mauvais exemple.

Supposons que vous ayez une classe de collection qui stocke, euh, des DVD, donc:

public class DVDCollection
{
    private Dictionary<string, DVD> store = null;
    private Dictionary<ProductId, string> dvdsByProductId = null;

    public DVDCollection()
    {
        // gets DVD data from somewhere and stores it *by* TITLE in "store"
        // stores a lookup set of DVD ProductId's and names in "dvdsByProductid"
        store = new Dictionary<string, DVD>();
        dvdsByProductId = new Dictionary<ProductId, string>();
    }

    // Get the DVD concerned, using an index, by product Id
    public DVD this[ProductId index]  
    {
       var title = dvdsByProductId[index];
       return store[title];
    }
}

Juste mon 2p, mais, comme je l’ai dit, .. j’ai toujours considéré un "indexeur" comme un moyen opportun d’obtenir des données de quelque chose.

32
Rob

Les exemples les plus évidents, comme mentionné par Skurmedel, sont List<T> et Dictionary<TKey, TValue>. Que préféreriez-vous à:

List<string> list = new List<string> { "a", "b", "c" };
string value = list[1]; // This is using an indexer

Dictionary<string, string> dictionary = new Dictionary<string, string>
{
    { "foo", "bar" },
    { "x", "y" }
};
string value = dictionary["x"]; // This is using an indexer

? Maintenant, il peut être relativement rare que vous ayez besoin de écrire un indexeur (généralement lorsque vous créez une classe semblable à une collection), mais je suppose que vous les utilisez assez raisonnablement.

24
Jon Skeet

Microsoft a un exemple utilisant un indexeur pour traiter un fichier comme un tableau d'octets.

public byte this[long index]
{
    // Read one byte at offset index and return it.
    get 
    {
        byte[] buffer = new byte[1];
        stream.Seek(index, SeekOrigin.Begin);
        stream.Read(buffer, 0, 1);
        return buffer[0];
    }
    // Write one byte at offset index and return it.
    set 
    {
        byte[] buffer = new byte[1] {value};
        stream.Seek(index, SeekOrigin.Begin);
        stream.Write(buffer, 0, 1);
    }
}
9
Robert Harvey

Supposons que vous souhaitiez pouvoir indexer une collection d'objets autrement que par l'ordre dans lequel elle a été placée dans une collection. Dans l'exemple ci-dessous, vous pouvez voir comment utiliser la propriété "Emplacement" d'un objet et en utilisant l'indexeur, renvoyer tous les objets de la collection qui correspondent à votre emplacement ou, dans le deuxième exemple, tous les objets contenant un certain nombre ) d'objets.

class MyCollection {

  public IEnumerable<MyObject> this[string indexer] {
    get{ return this.Where(p => p.Location == indexer); }
  }

  public IEnumerable<MyObject> this[int size] {
    get{ return this.Where(p => p.Count() == size);}
  }
}
5
scottm

Une fois que .NET a reçu les génériques, la raison principale pour laquelle j'ai implémenté un indexeur (pour implémenter une collection fortement typée) a disparu.

5
Daniel Pratt

Dans ASP.Net, un indexeur est utilisé à différents moments, par exemple pour lire quelque chose dans l'un des objets Request, Session ou Application. J'ai souvent vu où quelque chose est stocké dans l'objet Session ou Application uniquement pour être utilisé encore et encore.

3
JB King

C'est juste un sucre syntaxique pour les classes de type collection . Je n'ai jamais eu de raison d'écrire un tel cours. Je pense donc que ses utilisations sont très rares dans la "vraie vie", car les classes qui l'utilisent sont déjà implémentées.

3
Stefan Steinegger

http://code-kings.blogspot.in/2012/09/indexers-in-c-5.html

Les indexeurs sont des éléments d'un programme C # qui permettent à une classe de se comporter comme un tableau. Vous seriez en mesure d'utiliser toute la classe en tant que tableau. Dans ce tableau, vous pouvez stocker n'importe quel type de variables. Les variables sont stockées dans un emplacement distinct, mais adressées par le nom de la classe elle-même. Créer des indexeurs pour les entiers, les chaînes, les booléens, etc. serait une idée réalisable. Ces indexeurs agiraient effectivement sur des objets de la classe.

Supposons que vous ayez créé un indexeur de classe qui stocke le numéro de rôle d'un étudiant dans une classe. De plus, supposons que vous ayez créé un objet de cette classe nommé obj1. Lorsque vous dites obj1 [0], vous faites référence au premier élève du rôle. De même, obj1 [1] fait référence au deuxième élève inscrit. 

Par conséquent, l'objet utilise des valeurs indexées pour faire référence à la variable Integer stockée de manière privée ou publique dans la classe. Supposons que vous n’ayez pas cette possibilité, vous feriez probablement référence de la manière suivante (qui serait plus longue): 

obj1.RollNumberVariable[0]
obj1.RollNumberVariable[1]. 

où RollNumberVariable serait la variable Integer qui fait référence au numéro de rôle de l'objet étudiant en cours.

Pour plus de détails http://code-kings.blogspot.in/2012/09/indexers-in-c-5.html

2
code-kings
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace IndexerSample
{
    class FailSoftArray 
    {
        int[] a; // reference to underlying array
        public int Length; // Length is public
        public bool ErrFlag; // indicates outcome of last operation
        // Construct array given its size.
        public FailSoftArray(int size)
        {
            a = new int[size];
            Length = size;
        }
        // This is the indexer for FailSoftArray.
        public int this[int index] 
        {
        // This is the get accessor.
            get
            {
                if (ok(index))
                {
                    ErrFlag = false;
                    return a[index];
                }
                else
                {
                    ErrFlag = true;
                    return 0;
                }
            }
            // This is the set accessor.
            set
            {
                if (ok(index))
                {
                    a[index] = value;
                    ErrFlag = false;
                }
                else ErrFlag = true;
            }
        }
        // Return true if index is within bounds.
        private bool ok(int index)
        {
            if (index >= 0 & index < Length) return true;
            return false;
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            FailSoftArray fs = new FailSoftArray(5);
            int x;
            // Show quiet failures.
            Console.WriteLine("Fail quietly.");
            for (int i = 0; i < (fs.Length * 2); i++)
                fs[i] = i * 10;
            for (int i = 0; i < (fs.Length * 2); i++)
            {
                x = fs[i];
                if (x != -1) Console.Write(x + " ");
            }
            Console.WriteLine();
            // Now, display failures.
            Console.WriteLine("\nFail with error reports.");
            for (int i = 0; i < (fs.Length * 2); i++)
            {
                fs[i] = i * 10;
                if (fs.ErrFlag)
                    Console.WriteLine("fs[" + i + "] out-of-bounds");
            }
            for (int i = 0; i < (fs.Length * 2); i++)
            {
                x = fs[i];
                if (!fs.ErrFlag) Console.Write(x + " ");
                else
                    Console.WriteLine("fs[" + i + "] out-of-bounds");
            }
            Console.ReadLine();
        }
    }
}
2
Pranaya

Voici une vidéo que j'ai créée http://www.youtube.com/watch?v=HdtEQqu0yOY et ci-dessous une explication détaillée à propos de la même chose.

Les indexeurs permettent d’accéder à une collection contenue dans une classe à l’aide d’une interface simplifiée. C’est un sucre syntaxique. 

Par exemple, disons que vous avez une classe de clients avec une collection d'adresses à l'intérieur. Maintenant, disons que nous aimerions aller chercher la collection d’adresses par “Pincode” et “PhoneNumber”. La démarche logique consisterait donc à créer deux fonctions surchargées, l’une en utilisant «PhoneNumber» et l’autre avec «PinCode». Vous pouvez voir dans le code ci-dessous que nous avons deux fonctions définies.

Customer Customers = new Customer();
Customers.getAddress(1001);
Customers.getAddress("9090");

Si vous utilisez l'indexeur, vous pouvez simplifier le code ci-dessus avec quelque chose comme indiqué dans le code ci-dessous.

Customer Customers = new Customer();
Address o = Customers[10001];
o = Customers["4320948"];

À votre santé.

1
Shivprasad Koirala

J'essaie d'obtenir des images d'un fichier de séquence. J'ai besoin d'une sorte de tableau 2D ou un tableau dentelé pour contenir les valeurs de pixels. J'utilise des indexeurs au lieu de tableaux, car la boucle sur les indexeurs est plus rapide que sur des tableaux 2D ou déchiquetés.

0
user2330678

http://code-kings.blogspot.in/2012/09/indexers-in-c-5.html

en utilisant le système;

espace de noms Indexers_Example

{

class Indexers
{

    private Int16[] RollNumberVariable;

    public Indexers(Int16 size)
    {
        RollNumberVariable = new Int16[size];

        for (int i = 0; i < size; i++)
        {
            RollNumberVariable[i] = 0;
        }
    }

    public Int16 this[int pos]
    {
        get
        {
            return RollNumberVariable[pos];
        }
        set
        {
            RollNumberVariable[pos] = value;
        }
    }
}

}

0
code-kings

Vous pouvez utiliser un indexeur pour fournir avec élégance une synchronisation en lecture/écriture multi-threads à un dictionnaire non-thread-safe (ou à toute collection non-thread-safe):

internal class ThreadSafeIndexerClass
{
    public object this[int key]
    {
        get
        {
            // Aquire returns IDisposable and does Enter() Exit() on a certain ReaderWriterLockSlim instance
            using (_readLock.Aquire()) 
            {
                object subset;
                _dictionary.TryGetValue(key, out foundValue);
                return foundValue;
            }
        }
        set
        {
            // Aquire returns IDisposable and does Enter() Exit() on a certain ReaderWriterLockSlim instance
            using (_writeLock.Aquire())
                _dictionary[key] = value;
        }
    }
}

Utile surtout lorsque vous ne souhaitez pas utiliser le poids lourd ConcurrentDictionary (ou toute autre collection simultanée).

0
brakeroo

Ajout à @ code-kings post.

De plus, l'appel de RollNumberVariable[0] déclenchera le comportement de l'indexeur de la collection par défaut. Alors que les indexeurs sont en réalité propriétés , il est de votre part d’écrire votre propre logique lors de l’extraction de données. Vous pouvez facilement déléguer la plupart des valeurs de paramètre-index à la collection interne, mais vous pouvez également renvoyer toute valeur arbitraire pour certaines valeurs d'index.

Juste un exemple - vous pouvez avoir 2+ collections internes dans un format différent, mais l’utilisateur externe va interagir avec elles via un seul indexeur (qui fonctionnera un peu comme un répartiteur), alors que ces collections seront masquées. Cela encourage le principe de l’encapsulation.

0
Artur Udod