一个类型的多个索引属性?

时间:2011-01-18 23:26:52

标签: c# .net

在C#中可以有这样的东西吗?我不太确定:

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

所以可以这样使用:

myLibrary.Books["V For Vendetta"]
myLibrary.PublishingDates["V For Vendetta"] = ...

所以我需要在我的框架中实现的完整成员方法(通过调用它们)是:

GetCustomStringValue (key)
GetCustomIntValue (key)
GetCustomBoolValue (key)
GetCustomFloatValue (key)
SetCustomStringValue (key)
SetCustomIntValue (key)
SetCustomBoolValue (key)
SetCustomFloatValue (key)

我想用自己的类型实现它们更清洁。

5 个答案:

答案 0 :(得分:11)

唯一可以做到这一点的方法是让Books成为返回具有自己合适索引器的类型的属性。这是一种可能的方法:

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

但是你应该认真考虑提供IDictionary<,>的实现,而不是使用这种方法,因为它将允许其他漂亮的东西,比如枚举键值对等。

答案 1 :(得分:2)

在C#中,必须将索引器称为this(请参阅http://msdn.microsoft.com/en-us/library/aa664459(v=VS.71).aspx)。您可以重载索引器,但请记住,C#不允许仅基于返回类型进行重载。所以,你可以拥有:

public int this[int i]
public string this[string s]

你不能拥有:

public int this[int i]
public string this[int i]

.NET类库设计指南建议每个类只有一个索引器。

所以在你的情况下,没有办法只使用索引器做你想要的。

答案 2 :(得分:1)

不幸的是,C#不支持它。它只识别this[]属性,它在编译时实际上只是一个名为Item的可索引属性。 CLI支持任意数量的可索引属性,并且可以反映在F#等其他语言中,您可以在其中定义自己的属性。

即使你在CIL中定义了自己的,或者你仍然不能像你想要的那样从C#中调用它们,你需要手动调用get_Books(index);来获取一个名为{{的属性1}}。所有属性都只是方法调用的语法糖。 C#仅将名为Books的属性识别为可索引。

答案 3 :(得分:0)

为什么不使用方法?

class Library 
{     
    public string Books(string title)
    {         
        return this.GetBookByName(title);
    }      

    public DateTime PublishingDates(string title)
    {         
        return this.GetBookByName(title).PublishingDate;   
    } 
} 

答案 4 :(得分:0)

只是使用多个索引器参数的风格练习:

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"];