一般搜索 3 个单独的字典以获取值

Generically search 3 separate dictionaries for value

我有一个正在开发的在线游戏,我正在尝试以这种确切的方式解决如何使用通用搜索功能从 3 个不同的词典中获得单个结果。

这是为了玩家的视线,但不会在循环中使用。

    protected Dictionary<UInt32, Character> _currentVisibleCharacters;
    protected Dictionary<UInt32, Item> _currentVisibleMapItems;
    protected Dictionary<UInt32, Npc> _currentVisibleNpcs;

    public Boolean GetVisibleObject<TObject>(UInt32 objId, out TObject obj) 
        where TObject : WorldObject
    {
          //I need to be able to search all 3 dictionaries with this function.
    }

它应该使用 "objId" 在 3 个词典中的任何一个中搜索现有的 key/value 对。一旦找到,它应该将找到的值分配给参数"obj"。我尝试过使用 LINQ,但我 运行 遇到了分配问题,例如,从字段 _currentlyVisisbleNpcs 到 "obj" 参数的 Npc 值分配。

角色、物品和 Npc 继承自 WorldObject。

public TObject GetVisibleObject<TObject>(UInt32 objId) 
    where TObject : WorldObject, new()
{
     WorldObject match = null;

     match = _currentVisibleCharacters[objId];

     if (match == null)
        match = _currentVisibleMapItems[objId];

    if (match == null)
        match = _currentVisibleNpcs[objId];


    return (TObject)match;
}

由于存储在字典中的所有值都继承自 WorldObject,因此您可以return每个与 WorldObject 的潜在匹配,然后转换为更具体的 TObject 类型。

此外,return 直接使用类型,而不是使用输出,这更具可读性和可用性,除非您绝对需要布尔成功值,这应该从 TObject 是否为 null 来推断.

下面的测试代码return是字符类型的匹配项。

_currentVisibleCharacters = new Dictionary<UInt32, Character>();
_currentVisibleCharacters.Add(0, new Character());
var match = GetVisibleObject<Character>(0);
Console.WriteLine(match);
Console.WriteLine(match.GetType());

嗯,我试图通过介绍我自己的东西来简化它 class。

你可以把这个方法作为一个方向,因为我不知道你的class结构是怎样的:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApplication1
{
    class Character
    {
        public string Name { get; set; }
    }

    class Micky : Character
    {

    }

    class Minnie : Character
    {

    }

    class Program
    {
        static void Main(string[] args)
        {
            var mickeys = new Dictionary<Guid, Character>();
            var searchKey = Guid.NewGuid  ();
            mickeys.Add(searchKey, new Micky { Name = "Micky A"});
            mickeys.Add(Guid.NewGuid(), new Micky { Name = "Micky B" });

            var minnies = new Dictionary<Guid, Character>();
            minnies.Add(Guid.NewGuid(), new Minnie { Name = "Minnie A" });
            minnies.Add(Guid.NewGuid(), new Minnie { Name = "Minnie B" });


            var searchedItem = mickeys.Union(minnies).Where(k => k.Key == searchKey).FirstOrDefault();
            Console.WriteLine(searchedItem.Value.Name);

        }
    }
}

要考虑的要点:

  1. 您不需要创建 3 个字典,因为您可以创建一个字典(只要键是唯一的)。您可以创建一个父字典 class 并设置 N 个子字典的值。这一点会涵盖L的SOLID原则(LSP(Liskov substitution principle))

  2. 如果你想有一个单独的字典,那么用Union把它们组合起来,然后按键搜索。

我假设你需要检查类型,这样你就不会从错误的字典中得到东西。

    public Boolean GetVisibleObject<T>(UInt32 objId, out T obj) 
        where T : WorldObject
    {
          //I need to be able to search all 3 dictionaries with this function.
          //It should use "objId" to search for an existing key in either of the 3.

        obj = null;

        if (typeof(T) == typeof(Character))
        {
            if (_currentVisibleCharacters.ContainsKey(objId))
            {
                obj = _currentVisibleCharacters[objId] as T;
                return true;
            }
        }
        else if (typeof(T) == typeof(Item))
        {
            if (_currentVisibleMapItems.ContainsKey(objId))
            {
                obj = _currentVisibleMapItems[objId] as T;
                return true;
            }
        }
        else if (typeof(T) == typeof(Npc))
        {
            if (_currentVisibleNpcs.ContainsKey(objId))
            {
                obj = _currentVisibleNpcs[objId] as T;
                return true;
            }
        }           

        return false;

    }