Reputation: 331052
Is it possible to have something like this in C#? I am not very sure:
class Library
{
public string Books[string title]
{
get{return this.GetBookByName(string title);}
}
public DateTime PublishingDates[string title]
{
get{return this.GetBookByName(string title).PublishingDate;}
}
}
So it could be used as such:
myLibrary.Books["V For Vendetta"]
myLibrary.PublishingDates["V For Vendetta"] = ...
So my complete member methods that I need to implement in my framework (by calling them) are:
GetCustomStringValue (key)
GetCustomIntValue (key)
GetCustomBoolValue (key)
GetCustomFloatValue (key)
SetCustomStringValue (key)
SetCustomIntValue (key)
SetCustomBoolValue (key)
SetCustomFloatValue (key)
I want to implement them cleaner in my own type.
Upvotes: 7
Views: 4044
Reputation: 13306
Just an exercice of style using multiple indexer parameters:
enum Target
{
Books,
PublishingDates
}
class Book
{
public string Title { get; set; }
public DateTime PublishingDate { get; set; }
}
class Library
{
public object this[Target target, string title]
{
get
{
switch (target)
{
case Target.Books:
return GetBookByTitle(title);
case Target.PublishingDates:
return GetBookByTitle(title).PublishingDate;
default:
throw new ArgumentOutOfRangeException(nameof(target),
target, null);
}
}
}
static Book GetBookByTitle(string title)
{
return new Book {Title = "V For Vendetta"};
}
}
var book = (Book)myLibrary[Target.Books, "V For Vendetta"];
var dateTime = (DateTime)myLibrary[Target.PublishingDates, "V For Vendetta"];
Upvotes: 0
Reputation: 169018
The only way you could do this would be to have Books
be a property that returns a type that has its own suitable indexer. Here's one possible approach:
public class Indexer<TKey, TValue>
{
private Func<TKey, TValue> func;
public Indexer(Func<TKey, TValue> func)
{
if (func == null)
throw new ArgumentNullException("func");
this.func = func;
}
public TValue this[TKey key]
{
get { return func(key); }
}
}
class Library
{
public Indexer<string, Book> Books { get; private set; }
public Indexer<string, DateTime> PublishingDates { get; private set; }
public Library()
{
Books = new Indexer<string, Book>(GetBookByName);
PublishingDates = new Indexer<string, DateTime>(GetPublishingDate);
}
private Book GetBookByName(string bookName)
{
// ...
}
private DateTime GetPublishingDate(string bookName)
{
return GetBookByName(bookName).PublishingDate;
}
}
But you should seriously consider providing an implementation of IDictionary<,>
instead of using this approach, as it will allow other nifty stuff, like enumeration of key-value pairs, etc.
Upvotes: 12
Reputation: 134005
In C#, indexers have to be called this
(see http://msdn.microsoft.com/en-us/library/aa664459(v=VS.71).aspx). You can overload indexers, but remember that C# doesn't allow overloading based on return type only. So, whereas you can have:
public int this[int i]
public string this[string s]
You couldn't have:
public int this[int i]
public string this[int i]
The .NET class library design guidelines recommend having only one indexer per class.
So in your case, there's no way to do what you're asking using indexers only.
Upvotes: 2
Reputation: 13897
C# doesn't support it, unfortunately. It only recognises the this[]
property, which is really just an indexable property named Item
when compiled. The CLI supports any number of indexable properties though, and that can be reflected in some other languages like F#, where you can define your own.
Even when you do define your own in CIL or otherwise though, you still can't call them from C# like you would want to, you need to make a manual call to get_Books(index);
for a property named Books
. All properties are just syntactic sugar for method calls like that. C# only recognises the property named Item
as indexable.
Upvotes: 2
Reputation: 28718
Why not just use methods?
class Library
{
public string Books(string title)
{
return this.GetBookByName(title);
}
public DateTime PublishingDates(string title)
{
return this.GetBookByName(title).PublishingDate;
}
}
Upvotes: 0