This is not a technically correct way to use StackOverflow, but I found your idea so useful that I expanded it. I thought it would save people if I publish what I came up with and an example of how to use it.
First, I needed to support the get-only and set-only properties, so I changed your code a bit for these scenarios:
Get and install (very minor changes):
public class IndexedProperty<TIndex, TValue> { readonly Action<TIndex, TValue> SetAction; readonly Func<TIndex, TValue> GetFunc; public IndexedProperty(Func<TIndex, TValue> getFunc, Action<TIndex, TValue> setAction) { this.GetFunc = getFunc; this.SetAction = setAction; } public TValue this[TIndex i] { get { return GetFunc(i); } set { SetAction(i, value); } } }
Get only:
public class ReadOnlyIndexedProperty<TIndex, TValue> { readonly Func<TIndex, TValue> GetFunc; public ReadOnlyIndexedProperty(Func<TIndex, TValue> getFunc) { this.GetFunc = getFunc; } public TValue this[TIndex i] { get { return GetFunc(i); } } }
Installation only:
public class WriteOnlyIndexedProperty<TIndex, TValue> { readonly Action<TIndex, TValue> SetAction; public WriteOnlyIndexedProperty(Action<TIndex, TValue> setAction) { this.SetAction = setAction; } public TValue this[TIndex i] { set { SetAction(i, value); } } }
Example
Here is a simple use case. I inherit the collection and create a named indexer, as John Skeet called it. This example should be simple, impractical:
public class ExampleCollection<T> : Collection<T> { public IndexedProperty<int, T> ExampleProperty { get { return new IndexedProperty<int, T>(GetIndex, SetIndex); } } private T GetIndex(int index) { return this[index]; } private void SetIndex(int index, T value) { this[index] = value; } }
ExampleCollection in the Wild
This hastily constructed unit test shows what it looks like when you ExampleCollection in a project:
[TestClass] public class IndexPropertyTests { [TestMethod] public void IndexPropertyTest() { var MyExample = new ExampleCollection<string>(); MyExample.Add("a"); MyExample.Add("b"); Assert.IsTrue(MyExample.ExampleProperty[0] == "a"); Assert.IsTrue(MyExample.ExampleProperty[1] == "b"); MyExample.ExampleProperty[0] = "c"; Assert.IsTrue(MyExample.ExampleProperty[0] == "c"); } }
Finally, if you want to use versions only for receiving and installing, it looks like this:
public ReadOnlyIndexedProperty<int, T> ExampleProperty { get { return new ReadOnlyIndexedProperty<int, T>(GetIndex); } }
Or:
public WriteOnlyIndexedProperty<int, T> ExampleProperty { get { return new WriteOnlyIndexedProperty<int, T>(SetIndex); } }
In both cases, the result works exactly as you expect it to have the get-only / set-only property.