为List <object> </object>重载Bracket []运算符

时间:2014-06-19 10:42:12

标签: c# properties indexer

我在使用索引器处理对象列表时遇到了一些麻烦。我希望能够通过它的名称(字符串)而不是它的索引来访问列表中的每个对象。所以,我想重载[]运算符来实现这一点。到目前为止,我无法在智能感知中显示过载,此时它无法正常工作。到目前为止我所拥有的是:

一个名为MapInfo的类的单例对象:

MapInfo mi = MapInfo.Instance;

在MapInfo类中,我有一个Table对象列表:

    List<Table> tables;
    public List<Table> Tables
    {
        get { return tables; }
    }

最后在Tables类中我尝试过这个:

class Table : IEnumerable<Table>
{

    public Table this[string tableName]
    {
        get
        {
            foreach (Table table in this)
            {
                if (table.name == tableName)
                    return table;
            }
            return null;
        }
    }

我希望能够使用以下方式访问我的Table对象:

mi.Tables["SomeTableName"]

这是我第一次尝试这个,所以我不太确定我哪里出错了。

4 个答案:

答案 0 :(得分:1)

您正在重载Table类的索引器。你的代码结构出了问题。 Table类是IEnumerable<Table>,因此Table包含其他表。

因此,List<Table>将包含Table实例,而Table实例又包含Table实例。

使用mi.Tables["SomeTableName"],您尝试访问List的索引器,而不是Table的索引器。

为什么不在MapInfo中定义索引器?

答案 1 :(得分:1)

使用字典

Private Dictionary<String, Table> tables;
public Dictionary<String, Table> Tables
{
    get { return tables; }
}

然后:

class Table : IEnumerable<Table>
{
    public Table this[string tableName]
    {
        get
        {
            Table table;
            if(mi.tables.TryGetValue(tableName, out table))
            {
                return table;
            }
            else
            {
                return null;
            }
        }
    }
}

答案 2 :(得分:1)

你可以使用这样的方法

public class MapInfo {
    private readonly TableCollection _tables = new TableCollection();

    public TableCollection Tables {
        get { return _tables; }
    }
}

public class TableCollection : List<Table> {
    public Table this[string name] {
        get { return this.FirstOrDefault(t => t.Name == name); /*using System.Linq;*/ }
    }
}

public class Table {
    public string Name { get; set; }
}

或简单地使用字典(Dictionary<string, Table>),如Danaldo建议的那样。但不是他们两个,因为他编码=))

IMO,正确的方法是不要使用像这样的索引器,因为我看到有多个表可以使用&#39; unique&#39;您的收藏中的名称。我建议使用一个简单的表列表和一个像GetTableWithName这样的方法来使事情变得更清楚,因为索引器通常会给(假)你的数据是唯一的

或者您可以将FirstOrDefault的来电替换为SingleOrDefault,这将在内部确保如果有一个名为&#39;的名称&#39;没有其他元素具有相同的名称&#39;

答案 3 :(得分:0)

您对MapInfo / Table的实施并不适合让您做您想做的事。

MapInfo中Table的属性不能是表的列表,它必须是Table类型。然后你的Table类应该完全实现IEnumerable接口。 用LinqPad编写的快速示例:

class Table : IEnumerable<Table>
{
    public Table()
    {
        _tables = new Dictionary<string, Table>();
    }

    public string name { get; set; }
    Dictionary<string, Table> _tables;
    public void Add(string tname)
    {
        _tables.Add(tname, new Table { name = tname });
    }
    public Table this[string tableName]
    {
        get
        {
            Table table;
            if (_tables.TryGetValue(tableName, out table))
                return table;
            return null;
        }
    }


    public IEnumerator<Table> GetEnumerator()
    {
        return _tables.Values.GetEnumerator();
    }

    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
    {
        return this.GetEnumerator();
    }
}


void Main()
{
    MapInfo mi = new MapInfo();
    mi.Table["foo"].Dump();
}
class MapInfo
{
    public MapInfo()
    {
        Tables = new Table();
        test();
    }
    private void test()
    {
        Tables.Add("foo");
        Tables.Add("bar");
        Tables.Add("soom");
    }
    public Table Tables { get; set; }
}
相关问题