Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# .NET字典:获取或创建新字典_C#_.net_Dictionary_Insert Update - Fatal编程技术网

C# .NET字典:获取或创建新字典

C# .NET字典:获取或创建新字典,c#,.net,dictionary,insert-update,C#,.net,Dictionary,Insert Update,我经常发现自己创建了一个具有非平凡值类(例如)的代码,然后在填充数据时总是编写相同的代码模式 例如: var dict=newdictionary(); string key=“foo”; 字符串aValueForKey=“bar”; 也就是说,我想将“bar”插入对应于键“foo”的列表中,其中键“foo”可能不会映射到任何东西 这就是我使用不断重复模式的地方: 列出键值; 如果(!dict.TryGetValue(key,out keyValues)) dict.Add(key,keyVa

我经常发现自己创建了一个具有非平凡值类(例如)的代码,然后在填充数据时总是编写相同的代码模式

例如:

var dict=newdictionary();
string key=“foo”;
字符串aValueForKey=“bar”;
也就是说,我想将
“bar”
插入对应于键
“foo”
的列表中,其中键
“foo”
可能不会映射到任何东西

这就是我使用不断重复模式的地方:

列出键值;
如果(!dict.TryGetValue(key,out keyValues))
dict.Add(key,keyValues=new List());
添加(aValueForKey);
有没有更优雅的方法

无法回答此问题的相关问题:


我们对此的理解略有不同,但效果相似:

public static TValue GetOrCreate<TKey, TValue>(this IDictionary<TKey, TValue> dict, TKey key) 
    where TValue : new()
{
    if (!dict.TryGetValue(key, out TValue val))
    {
        val = new TValue();
        dict.Add(key, val);
    }

    return val;
}

大多数情况下,使用该类型的人在顶部定义了
using
语句,因此IntelliSense也会在您的代码中找到它的扩展方法。

与许多编程问题一样,当您发现自己做了很多事情时,将其重构为一个方法:

public static void MyAdd<TKey, TCollection, TValue>(
    this Dictionary<TKey, TCollection> dictionary, TKey key, TValue value)
    where TCollection : ICollection<TValue>, new()
{
    TCollection collection;
    if (!dictionary.TryGetValue(key, out collection))
    {
        collection = new TCollection();
        dictionary.Add(key, collection);
    }
    collection.Add(value);
}
publicstaticvoidmyadd(
这本字典(字典,TKey键,TValue值)
其中TCollection:ICollection,new()
{
t收集;
if(!dictionary.TryGetValue(键,输出集合))
{
collection=新的TCollection();
添加(键、集合);
}
收藏。增值;
}

好的,不同的方法:

public static bool TryAddValue<TKey,TValue>(this System.Collections.Generic.IDictionary<TKey,List<TValue>> dictionary, TKey key, TValue value)
    {
        // Null check (useful or not, depending on your null checking approach)
        if (value == null)
            return false;

        List<TValue> tempValue = default(List<TValue>);

        try
        {
            if (!dictionary.TryGetValue(key, out tempValue))
            {
                dictionary.Add(key, tempValue = new List<TValue>());
            }
            else
            {
                // Double null check (useful or not, depending on your null checking approach)
                if (tempValue == null)
                {
                    dictionary[key] = (tempValue = new List<TValue>());
                }
            }

            tempValue.Add(value);
            return true;
        }
        catch
        {
            return false;
        }
    }
public static bool TryAddValue(此System.Collections.Generic.IDictionary dictionary、TKey、TValue值)
{
//空检查(有用与否,取决于空检查方法)
如果(值==null)
返回false;
List tempValue=默认值(List);
尝试
{
if(!dictionary.TryGetValue(key,out tempValue))
{
Add(key,tempValue=newlist());
}
其他的
{
//双重空检查(有用与否,取决于空检查方法)
if(tempValue==null)
{
字典[键]=(tempValue=新列表());
}
}
tempValue.Add(value);
返回true;
}
抓住
{
返回false;
}
}
通过这种方式,您必须“尝试添加”您的值到一个泛型列表(显然可以泛化到泛型集合)、空检查并尝试获取字典中的现有键/值。 用法和示例:

var x = new Dictionary<string,List<string>>();
x.TryAddValue("test", null); // return false due to null value. Doesn't add the key
x.TryAddValue("test", "ok"); // it works adding the key/value
x.TryAddValue("test", "ok again"); // it works adding the value to the existing list
var x=newdictionary();
x、 TryAddValue(“测试”,null);//由于值为null,返回false。不添加密钥
x、 TryAddValue(“测试”、“确定”);//它可以添加键/值
x、 TryAddValue(“测试”,“再次确定”);//将值添加到现有列表中会起作用
希望有帮助。

这个怎么样

var keyValues = dictionary[key] = dictionary.ContainsKey(key) ? dictionary[key] : new List<string>();
keyValues.Add(aValueForKey);
var-keyValues=dictionary[key]=dictionary.ContainsKey(key)?字典[键]:新列表();
添加(aValueForKey);

如果使用.Net Core,则可以使用

var dict=newdictionary();
dict.TryAdd(“foo”,“bar”);//返回bool,无论它是否已添加,请随意忽略。
var myValue=dict[“foo”];

如果构造函数需要参数,这里有一个解决方案

public static TValue GetOrCreate<TKey, TValue>(this IDictionary<TKey, TValue> dict, TKey key, Func<TValue> createNew)
    {
        if (!dict.TryGetValue(key, out var val))
        {
            val = createNew();
            dict.Add(key, val);
        }

        return val;
    }

对于更多的读者,以下是我认为合适的每种口味的一些扩展。如果需要检查是否添加了值,也可以使用
out
参数执行操作,但我认为可以使用
containskey
或其他已添加的参数

您可以使用
GetOrAddNew
检索项目,或创建项目并将其添加到dict。您可以使用
GetOrAdd
的各种重载添加新值。这可能是
默认值
,例如
NULL
0
,但您也可以提供lambda来为您构造对象,并使用任何类型的构造函数参数

var x = new Dictionary<string, int>();
var val = x.GetOrAdd("MyKey", (dict, key) => dict.Count + 2);
var val2 = x.GetOrAdd("MyKey", () => Convert.ToInt32("2"));
var val3 = x.GetOrAdd("MyKey", 1);
var x=newdictionary();
var val=x.GetOrAdd(“我的密钥”(dict,key)=>dict.Count+2);
var val2=x.GetOrAdd(“MyKey”,()=>Convert.ToInt32(“2”);
var val3=x.GetOrAdd(“MyKey”,1);
//
///扩展用于处理
/// 
公共静态类字典扩展
{
公共静态TValue GetOrAddNew(此IDictionary dict,TKey-key,TValue-defaultValue=default)
其中TValue:new()
=>dict.GetOrAdd(key,(values,innerKey)=>EqualityComparer.Default.Equals(Default(TValue),defaultValue)?new TValue():defaultValue);
公共静态TValue GetOrAdd(此IDictionary dict,TKey-key,TValue-defaultValue=default)
=>dict.GetOrAdd(键,(值,内部键)=>defaultValue);
公共静态TValue GetOrAdd(此IDictionary dict、TKey key、Func valueProvider)
=>dict.GetOrAdd(key,(values,innerKey)=>valueProvider());
公共静态TValue GetOrAdd(此IDictionary dict、TKey key、Func valueProvider)
=>dict.GetOrAdd(key,(values,innerKey)=>valueProvider(key));
公共静态TValue GetOrAdd(此IDictionary dict、TKey key、Func valueProvider)
{
如果(dict==null)抛出新的ArgumentNullException(nameof(dict));
如果(key==null)抛出新的ArgumentNullException(nameof(key));
如果(valueProvider==null)抛出新的ArgumentNullException(nameof(valueProvider));
if(dict.TryGetValue(键,输出值))
返回值;
dict[key]=值提供程序(dict,key);
返回dict[键];
}
}

我缺少
字典
的GetOrAdd,它确实存在于
ConcurrentDictionary

ConcurrentDictionary<int,Guid> Conversion = new ConcurrentDictionary<int, Guid>();
List<int> before = new List<int> { 1, 2, 1, 3 };
List<Guid> after = before.Select(x => Conversion.GetOrAdd(x, Guid.NewGuid())).ToList();

@Darthenius不,第一种方法是针对列表的(对于
HashSet
和其他
Dictionary
项,我们有其他方法)。我记不起e了
public static TValue GetOrCreate<TKey, TValue>(this IDictionary<TKey, TValue> dict, TKey key, Func<TValue> createNew)
    {
        if (!dict.TryGetValue(key, out var val))
        {
            val = createNew();
            dict.Add(key, val);
        }

        return val;
    }
MyDict.GetOrCreate(si.Id, createNew: () => new ObjectKnowingItsId(si.Id))
var x = new Dictionary<string, int>();
var val = x.GetOrAdd("MyKey", (dict, key) => dict.Count + 2);
var val2 = x.GetOrAdd("MyKey", () => Convert.ToInt32("2"));
var val3 = x.GetOrAdd("MyKey", 1);
    /// <summary>
    /// Extensions for dealing with <see cref="Dictionary{TKey,TValue}"/>
    /// </summary>
    public static class DictionaryExtensions
    {
        public static TValue GetOrAddNew<TKey, TValue>(this IDictionary<TKey, TValue> dict, TKey key, TValue defaultValue = default) 
            where TValue : new() 
            => dict.GetOrAdd(key, (values, innerKey) => EqualityComparer<TValue>.Default.Equals(default(TValue), defaultValue) ? new TValue() : defaultValue);

        public static TValue GetOrAdd<TKey, TValue>(this IDictionary<TKey, TValue> dict, TKey key, TValue defaultValue = default)
            => dict.GetOrAdd(key, (values, innerKey) => defaultValue);

        public static TValue GetOrAdd<TKey, TValue>(this IDictionary<TKey, TValue> dict, TKey key, Func<TValue> valueProvider)
            => dict.GetOrAdd(key, (values, innerKey) => valueProvider());

        public static TValue GetOrAdd<TKey, TValue>(this IDictionary<TKey, TValue> dict, TKey key, Func<TKey, TValue> valueProvider)
            => dict.GetOrAdd(key, (values, innerKey) => valueProvider(key));

        public static TValue GetOrAdd<TKey, TValue>(this IDictionary<TKey, TValue> dict, TKey key, Func<IDictionary<TKey, TValue>, TKey, TValue> valueProvider)
        {
            if (dict == null) throw new ArgumentNullException(nameof(dict));
            if (key == null) throw new ArgumentNullException(nameof(key));
            if (valueProvider == null) throw new ArgumentNullException(nameof(valueProvider));

            if (dict.TryGetValue(key, out var foundValue))
                return foundValue;

            dict[key] = valueProvider(dict, key);
            return dict[key];
        }
    }
ConcurrentDictionary<int,Guid> Conversion = new ConcurrentDictionary<int, Guid>();
List<int> before = new List<int> { 1, 2, 1, 3 };
List<Guid> after = before.Select(x => Conversion.GetOrAdd(x, Guid.NewGuid())).ToList();
ConcurrentDictionary<int, List<String>> dict;
keyValues = dict.GetOrAdd(key, new List<String>());
keyValues.Add(aValueForKey);