Je sais, je sais... La réponse d'Eric Lippert à ce genre de question est généralement quelque chose du genre "parce que cela ne valait pas la peine de le concevoir, implémenter, tester et le documenter".
Mais quand même, j'aimerais une meilleure explication... Je lisais ce billet de blog sur les nouvelles fonctionnalités de C# 4, et dans la section sur COM Interop, la partie suivante a attiré mon attention :
En passant, ce code utilise une nouvelle fonctionnalité de plus : les propriétés indexées (jetez un œil aux crochets après Range.) Mais cette fonctionnalité est disponible uniquement pour COM interop ; vous ne pouvez pas créer vos propres propriétés indexées en C# 4.0.
D'accord, mais pourquoi ? Je savais déjà et regrettait qu'il n'était pas possible de créer des propriétés indexées en C#, mais cette phrase m'a fait réfléchir à nouveau. Je vois plusieurs bonnes raisons de l'implémenter :
- le CLR le prend en charge (par exemple,
PropertyInfo.GetValue
a un paramètreindex
), c'est donc dommage de ne pas pouvoir en profiter en C# - il est pris en charge pour COM Interop, comme le montre l'article (en utilisant la dispatch dynamique)
- il est implémenté dans VB.NET
- il est déjà possible de créer des indexeurs, c'est-à-dire d'appliquer un index à l'objet lui-même, donc ce ne serait probablement pas compliqué d'étendre l'idée aux propriétés, en conservant la même syntaxe et en remplaçant simplement
this
par un nom de propriété
Cela permettrait d'écrire ce genre de choses :
public class Foo
{
private string[] _values = new string[3];
public string Values[int index]
{
get { return _values[index]; }
set { _values[index] = value; }
}
}
Actuellement, la seule solution de contournement que je connais est de créer une classe interne (ValuesCollection
par exemple) qui implémente un indexeur, et de modifier la propriété Values
pour qu'elle renvoie une instance de cette classe interne.
C'est très facile à faire, mais ennuyeux... Donc peut-être que le compilateur pourrait le faire pour nous ! Une option serait de générer une classe interne qui implémente l'indexeur, et de l'exposer via une interface générique publique :
// interface définie dans l'espace de noms System
public interface IIndexer
{
TValue this[TIndex index] { get; set; }
}
public class Foo
{
private string[] _values = new string[3];
private class <>c__DisplayClass1 : IIndexer
{
private Foo _foo;
public <>c__DisplayClass1(Foo foo)
{
_foo = foo;
}
public string this[int index]
{
get { return _foo._values[index]; }
set { _foo._values[index] = value; }
}
}
private IIndexer <>f__valuesIndexer;
public IIndexer Values
{
get
{
if (<>f__valuesIndexer == null)
<>f__valuesIndexer = new <>c__DisplayClass1(this);
return <>f__valuesIndexer;
}
}
}
Mais bien sûr, dans ce cas, la propriété retournerait en fait un IIndexer
, et ne serait pas vraiment une propriété indexée... Il serait préférable de générer une véritable propriété indexée CLR.
Qu'en pensez-vous ? Aimeriez-vous voir cette fonctionnalité en C# ? Sinon, pourquoi ?