none
如何实现同时支持数值索引和字符串索引的链式结构 RRS feed

  • 问题

  • 一个链式结构,可通过.Add(string name)追加一个指定名字的空元素到链尾
    也可以通过.Add(Typeof(item) item)追加一个元素到链尾

    如何让name和item一一对应起来呢?

    当通过字符串索引来访问这个链的时候,怎样根据name来获得item的地址呢?

    2013年5月21日 9:54

答案

  • 是的,具体重写你也可以用反射工具查看源码来实现你重写的代码,如果解决希望可以分享到这里来。

    If my post is helpful,please help to vote as helpful, if my post solve your question, please help to make it as answer. my sample

    • 已标记为答案 Yawness 2013年5月22日 8:49
    2013年5月22日 7:34

全部回复

  • 我没明白你具体的意图的,能不能给点示例代码来说明下的,或者解释详细点的,这样可以更好地让我们帮助你解决这个问题的,谢谢

    If my post is helpful,please help to vote as helpful, if my post solve your question, please help to make it as answer. my sample

    2013年5月22日 2:51
  • 对不起哦。可能上面表达得不是很规范,但是要给出代码也不可能(要是有代码,甚至知道原理就不会求助这个问题了)。
    我就给个应用的例子吧:

    假设有个类node

    class node{

    public node(){...}

    public node(string name){...}

    private string name;

    ...//其它成员和方法

    public string Name{

     Get{return this.name;}

     Set{this.name=value;}

     }

    }

    现在有这样一个链表

    SmartList<node> slist=new SmartList<node>();

    slist.Add("A");//隐式构造一个名为A的node,并追加到链尾
    或者

    node n=new node("B");

    slist.Add(n);//显式构造一个名为B的node,并追加到链尾

    可以通过slist[0]或者slist["A"]来访问node元素,而且当试图添加同名的元素,能够捕捉到重名异常;当试图更改元素的名字为一个已有名字时,也能捕捉到这个异常。

    具体的问题是这样的SmartList该如何实现

    2013年5月22日 3:16
  • 用一个stringditionary来做索引,在列表中增删的时候更新索引


    Visual C++ MVP

    2013年5月22日 3:46
    版主
  • stringditionary只能添加string类型的Value呀,可上面示例中的node不一定是string啊
    2013年5月22日 4:05
  • 我觉得可以使用Dictionary<TKey,TValue>这个类来实现你说的需求的,具体看参考:

    Dictionary<TKey, TValue> 类


    If my post is helpful,please help to vote as helpful, if my post solve your question, please help to make it as answer. my sample

    2013年5月22日 5:25
  • 我觉得可以使用Dictionary<TKey,TValue>这个类来实现你说的需求的,具体看参考:

    Dictionary<TKey, TValue> 类


    If my post is helpful,please help to vote as helpful, if my post solve your question, please help to make it as answer. my sample

    dictionary.Value属性是只读的,那么写索引器时,Set{...}就没法写了……

    是我利用dictionary的方法不对吗(我用了一个泛型List<Dictionary<string, T>>,然后写索引器时遇到了只读的问题)
    2013年5月22日 6:11
  • 如果使用这个类只存在这个只读的问题的话,你可以用继承这个类来重写它的索引器,使你继承的类可以使可读写的。

    If my post is helpful,please help to vote as helpful, if my post solve your question, please help to make it as answer. my sample

    2013年5月22日 6:47
  • 如果使用这个类只存在这个只读的问题的话,你可以用继承这个类来重写它的索引器,使你继承的类可以使可读写的。

    If my post is helpful,please help to vote as helpful, if my post solve your question, please help to make it as answer. my sample

    也就是说我用泛型List<Dictionary<string, T>>的思路是可行的?那我去试试 override,不知道还会遇到什么问题。

    一开始考虑的方面本来想得挺简单的,没想到稍微一深入就遇到这么多要面对的问题……

    2013年5月22日 7:11
  • 是的,具体重写你也可以用反射工具查看源码来实现你重写的代码,如果解决希望可以分享到这里来。

    If my post is helpful,please help to vote as helpful, if my post solve your question, please help to make it as answer. my sample

    • 已标记为答案 Yawness 2013年5月22日 8:49
    2013年5月22日 7:34
  • 嗯,希望能解决^_^
    2013年5月22日 8:50
  • using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;

    namespace MyCollections
    {
        class MyCollection<T> : System.Collections.ObjectModel.Collection<T>  where T : System.Windows.Forms.Control, new()
        {
            public void Add(string name)
            {
                if (!this.IsUniqueName(name))
                    throw new ArgumentException("Name Already Exists");

                T item = new T();
                item.Name = name;

                base.Add(item);
            }

            public virtual T FindByName(string name)
            {
                foreach (T item in this)
                {
                    if (item.Name == name)
                        return item;
                }
                return default(T);
            }

            public int IndexOf(string name)
            {
                int index = 0;
                foreach (T item in this)
                {
                    if (item.Name == name)
                    {
                        return index;
                    }
                    index++;
                }
                return -1;
            }

            public virtual bool IsUniqueName(string name)
            {
                return (this.FindByName(name) == null);
            }

            protected override void InsertItem(int index, T item)
            {
                if (string.IsNullOrEmpty(item.Name))
                    item.Name = this.NextUniQuename();
                else if (!this.IsUniqueName(item.Name))
                {
                    throw new ArgumentException("Name Already Exists");
                }
                base.InsertItem(index, item);
            }

            public virtual string NextUniQuename()
            {
                string namePrefix = typeof(T).Name;
                string name = string.Empty;
                for (int i = 0; i < 0x7fffffff; i++)
                {
                    name = namePrefix + i.ToString();
                    if (this.IsUniqueName(name))
                        return name;
                }
                return name;
            }

            protected override void RemoveItem(int index)
            {
                base.RemoveItem(index);
            }

            protected override void SetItem(int index, T item)
            {
                if (string.IsNullOrEmpty(item.Name))
                {
                    item.Name = this.NextUniQuename();
                }
                else if (!this.IsUniqueName(item.Name))
                {
                    throw new ArgumentException("Name Already Exists");
                }
                base.SetItem(index, item);
            }

            public T this[string name]
            {
                get
                {
                    int index = this.IndexOf(name);
                    if (index == -1)
                        throw new ArgumentException("Name Dosen't Exists");
                    return base[index];
                }
                set
                {
                    int indexByName = this.IndexOf(name);
                    int indexByValue = base.IndexOf(value);
                    bool hasName = indexByName > -1;
                    bool hasValue = indexByValue > -1;
                    if (!hasValue)
                    {
                        if (hasName)
                        {
                            base[indexByName] = value;
                        }
                        else
                            throw new ArgumentException("Name Dosen't Exists");//试图向不存在的元素同赋值
                    }
                    else
                    {
                        if (!hasName)
                        {
                            throw new ArgumentException("Name Dosen't Exists");//试图向不存在的元素同赋值
                        }
                        else if (hasName && (indexByName != indexByValue))
                        {
                            throw new ArgumentException("Name Already Exists");//试图向已存在的元素赋值,而值与现有的元素发生重名
                        }
                    }
                }
            }
        }
    }
    2013年5月23日 6:13