Unity3d+c#:Dictionary多个key查找一个value,重载Equals

本文介绍了如何在C#中通过重写Equals与GetHashCode方法来实现自定义类型的哈希表和字典。提供了DataKey系列类的具体实现示例,并展示了如何使用这些类构建TableData泛型字典。

Equals与GetHashCode

System.Object声明方法Equals和GetHashCode以及其他成员。 (注意:这个案例在C#中很重要)。您创建的类型会自动继承这些方法。

Equals的任务是将一个对象与另一个对象进行比较。引用类型的默认实现是比较引用。如果你想改变这种行为,你将不得不重写这个方法。

GetHashCode计算对象的哈希码并用于哈希表。例如,类型Dictionary<TKey,TValue>和HashSet利用它。 请参阅Hashtable and Dictionary Collection Types。如果您覆盖Equals,则必须覆盖GetHashCode以保持一致性。

DataKey1

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

namespace DictionaryEx
{
    public class DataKey1
    {
        public int mKey1;

        public DataKey1(int key)
        {
            mKey1 = key;
        }

        public override bool Equals(object obj)
        {
            if (obj == null) return false;
            DataKey1 key = obj as DataKey1;
            if (key == null) return false;

            return this.mKey1 == key.mKey1;
        }

        public override int GetHashCode()
        {
            return mKey1.GetHashCode();
        }
    }

    public class DataKey2 : DataKey1
    {
        public int mKey2;

        public DataKey2(int key1, int key2)
            : base(key1)
        {
            mKey2 = key2;
        }

        public override bool Equals(object obj)
        {
            if (obj == null) return false;
            DataKey2 key = obj as DataKey2;
            if (key == null) return false;

            return this.mKey1 == key.mKey1 && this.mKey2 == key.mKey2;
        }

        public override int GetHashCode()
        {

            return base.GetHashCode() ^ mKey2.GetHashCode();
        }
    }

    public class DataKey3 : DataKey2
    {
        public int mKey3;

        public DataKey3(int key1, int key2, int key3)
            : base(key1, key2)
        {
            mKey3 = key3;
        }

        public override bool Equals(object obj)
        {
            if (obj == null) return false;
            DataKey3 key = obj as DataKey3;
            if (key == null) return false;

            return this.mKey3 == key.mKey3 && this.mKey2 == key.mKey2 && this.mKey1 == key.mKey1;
        }

        public override int GetHashCode()
        {
            return base.GetHashCode() ^ mKey3.GetHashCode();
        }
    }

    public class DataKey4 : DataKey3
    {
        public int mKey4;

        public DataKey4(int key1, int key2, int key3, int key4)
            : base(key1, key2, key3)
        {
            mKey4 = key4;
        }

        public override bool Equals(object obj)
        {
            if (obj == null) return false;
            DataKey4 key = obj as DataKey4;
            if (key == null) return false;

            return this.mKey4 == key.mKey4 && this.mKey3 == key.mKey3 && this.mKey2 == key.mKey2 && this.mKey1 == key.mKey1;
        }

        public override int GetHashCode()
        {
            return base.GetHashCode() ^ mKey4.GetHashCode();
        }
    }
}

重载 public override bool Equals(object obj)
使类的比较为比较里面的成员变量int值

TableData

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

namespace DictionaryEx
{
    public class TableData<K, T> //: CountString
        where K : DataKey1
    {
        protected const int mcHeadSize = 140;
        protected string mTableName;
        protected string mChineseTableName = "";
        protected int mTimeStamp;
        protected int mCurSeq;
        protected Dictionary<K, T> mTableData = new Dictionary<K, T>(131);

        protected List<T> mTableDataSequence = new List<T>(128);		

        public TableData(string tableName, string strChineseTableName)
        {
            mTableName = tableName;
            mChineseTableName = strChineseTableName;//上线后屏蔽
        }

        public TableData()
        {
            
        }

        public string name
        {
            get
            {
                return mTableName;
            }
        }

        public int timeStamp
        {
            set
            {
                mTimeStamp = value;
            }
            get
            {
                return mTimeStamp;
            }
        }

        public int curSeq
        {
            set
            {
                mCurSeq = value;
            }
            get
            {
                return mCurSeq;
            }
        }

        // 
        public List<T> GetTableSequenceData()
        {
            return mTableDataSequence;
        }

        public Dictionary<K, T> GetTableKeyValueData()
        {
            return mTableData;
        }

        public Int32 Count()
        {
            return mTableData.Count;
        }

        public T Find(K key)
        {
            T ret;

            if (mTableData.TryGetValue(key, out ret)) return ret;
            return default(T); //此关键字对于引用类型会返回空,对于数值类型会返回零。对于结构,此关键字将返回初始化为零或空的每个结构成员
        }

        public void Add(K key,T data)
        {
            mTableDataSequence.Add(data);
            mTableData.Add(key, data);
        }

        public void Remove(K key)
        {
            T data;
            if (mTableData.TryGetValue(key, out data))
            {
                mTableDataSequence.Remove(data);
                mTableData.Remove(key);
            }
        }
    }
}

使用与测试

TableData<DataKey2, int> dic = new TableData<DataKey2, int>();
            dic.Add(new DataKey2(1, 2), 1);
            dic.Add(new DataKey2(3,4), 2);

            Debug.Log(dic.Find(new DataKey2(1, 2)));

源码

https://github.com/luoyikun/UnityForTest
DictionaryExScene场景

C# 中,如果你需要使用**两个 key 的组合**来对应一个 value,可以采用以下几种方式来实现: ### 方法一:使用元组(Tuple)作为键 C# 支持使用元组作为 `Dictionary` 的键,这样可以轻松地将两个 key 组合成一个键。 ```csharp using System; using System.Collections.Generic; class Program { static void Main() { // 使用元组 (key1, key2) 作为键 Dictionary<(string, int), string> map = new Dictionary<(string, int), string>(); // 添加组合键值对 map.Add(("apple", 1), "A"); map.Add(("banana", 2), "B"); // 获取值 if (map.TryGetValue(("apple", 1), out string value)) { Console.WriteLine("Value: " + value); // 输出 A } } } ``` ### 方法二:自定义类或结构体作为键 你可以定义一个类或结构体来表示组合键,并重写 `Equals()` 和 `GetHashCode()` 方法以确保字典能正确识别键。 ```csharp using System; using System.Collections.Generic; class Program { struct CompositeKey { public string Key1 { get; } public int Key2 { get; } public CompositeKey(string key1, int key2) { Key1 = key1; Key2 = key2; } public override bool Equals(object obj) { if (obj is CompositeKey other) { return Key1 == other.Key1 && Key2 == other.Key2; } return false; } public override int GetHashCode() { unchecked { return (Key1?.GetHashCode() ?? 0) * 17 + Key2.GetHashCode(); } } } static void Main() { Dictionary<CompositeKey, string> map = new Dictionary<CompositeKey, string>(); var key1 = new CompositeKey("apple", 1); map[key1] = "Apple Info"; var lookupKey = new CompositeKey("apple", 1); if (map.TryGetValue(lookupKey, out string value)) { Console.WriteLine(value); // 输出 Apple Info } } } ``` --- ### 总结 - 使用 `(key1, key2)` 元组是最简单的方式。 - 如果需要更复杂的键结构或更好的可读性,可以使用自定义的类或结构体。 - 注意:自定义类型必须正确实现 `Equals()` 和 `GetHashCode()`,否则字典无法正常工作。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

四夕立羽

你的鼓励将是我创作的最大动力。

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值