值为不同数据类型数组的字典

4
我正在尝试创建一个包含整数、字符串和布尔值数据类型的数组作为值的字典。我想使用object[]作为值,因此声明如下所示:
Dictionary<long, object[]> netObjectArray = new Dictionary<long, object[]>();

每当我尝试将其元素的值设置为某些内容时,VS会提示字典中找不到该键。
netObjectArray[key][2] = val; // ex: The given key was not present in the dictionary.

我该如何正确处理这个问题?

更新1: 在抛出此异常之前,其他字典以类似的方式使用时没有任何问题:

Dictionary<long, Vector2> netPositions = new Dictionary<long, Vector2>();
netPositions[key] = new Vector2(x, y); // works ok

在这个例子中,locals 显示了已经赋值的内容,字典现在包含该条目。为什么我的其他字典不是这种情况呢?

解决方案: 在写入值到一个值数组之前,我们必须先初始化该数组。以下代码对我有效:

try { netObjectArray[key] = netObjectArray[key]; } // if the object is undefined,
catch { netObjectArray[key] = new object[123]; } // this part will create an object
netObjectArray[key][0] = new Vector2(x, y) as object; // and now we can assign a value to it :)

3
你是否已经将 netObjectArray[key] 初始化至少为 new object[2] - Albin Sunnanbo
3
此外,将不同类型的数据存储在字典中是一种糟糕的代码设计。你真的需要这么做吗?还是可以以更好的格式封装数据? - Albin Sunnanbo
你可以使用 Tuple<int,string,bool> 作为值。http://msdn.microsoft.com/zh-cn/library/system.tuple.aspx - Tim Schmelter
7
创建一个包含所有信息的Player类,并拥有一个Player字典。 - Servy
1
@Servy 我希望我可以多次给你的评论点赞:这正是数组不好而类非常优秀的情况。 - Sergey Kalinichenko
显示剩余4条评论
3个回答

6
这是预期的行为:如果在Dictionary<K,V>中没有该键,则尝试读取该键时会失败。在访问之前,应将空数组分配给key元素。
以下是访问字典的典型模式,当您不确定键是否存在时:
object[] data;
if (!netObjectArray.TryGetValue(key, out data)) {
    data = new object[MyObjCount];
    netObjectArray.Add(key, data);
}
data[2] = val;

编辑(针对问题的编辑)

只有当你尝试读取之前未知的键时,才会看到异常。像你这样的分配操作:

netPositions[key] = new Vector2(x, y);

即使在分配时字典中没有该键,也可以使用:这将在您的字典上执行“插入或更新”操作。


那么,为什么 netPositions[key] = new Vector2(x, y); 不会引起异常,而紧接着的 netObjectArray[key][2] = val; 却会呢?是因为 new 部分被允许而简单的设置不被允许吗? - user1306322
@user1306322 请查看我的编辑。基本上,不允许读取未知的键,但写入未知的键是可以的。 - Sergey Kalinichenko
我的评论是回应你的编辑。据我所知,我正在连续写入两个先前未定义的值。你说要抛出异常,我需要尝试读取所选位置的未定义值,但我在代码中没有这样做。好的,虚惊一场答案在下面的评论中[https://dev59.com/mmLVa4cB1Zd3GeqPxIru#x4XinYgBc1ULPQZF2RM8]。 - user1306322
2
@user1306322,您确实进行了读取操作,但是方式有些难以理解:netObjectArray[key][2] = val 等同于 (netObjectArray[key])[2] = val,而 netObjectArray[key] 则是尝试在 key 处读取对象数组。赋值操作的写入部分与您获取的对象数组不符。 - Sergey Kalinichenko

1
尝试像这样做:

Dictionary<long, object[]> netObjectArray = new Dictionary<long, object[]>();
for (int i = 0; i < 100; i++) netObjectArray[i] = new object[100];//This is what you're missing.
netObjectArray[key][2] = val;

你能解释一下为什么在数组字典中缺失它,而通常的字典却没有问题吗? - user1306322
1
我的猜测是:在你的Dictionary<long, Vector2>中,你应该将Vector2放在netPositions[key]中,这一步是正确的。但是在Dictionary<long, object[]>中,你没有将object[]放在netObjectArray[key]中(这一步是你应该做的),你跳过了这一步。你试图访问一个不存在的object[] - ispiro
是的,我正在尝试向先前未定义的值数组中写入一个值。眼力不错。 - user1306322
假设我正确理解了long是玩家编号,现在你想要“初始化”一个新玩家:添加 long numberOfPlayers = 0; 到某个位置。然后: void AddPlayer() { netObjectArray[numberOfPlayers++] = new object[100]; }//注意:只有在操作之后numberOfPlayers才会被增加。根据需要调整。 - ispiro
1
但是我实际上建议采取Servy的建议,为每个玩家的“属性”创建一个类。 - ispiro

0
Dictionary<string, object[]> complex = new Dictionary<string, object[]>();

complex.Add("1", new object[] { 1, 2 });

object[] value = complex["1"];
value[1] = val;

对我来说可行...


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接