是否可以创建一个'自初始化'c# 6.0中的字典扩展方法

本文关键字:方法 扩展 字典 初始化 一个 是否 创建 | 更新日期: 2023-09-27 18:15:16

是否有可能在字典上创建一个扩展方法,如果字典为空,则能够自我初始化?

我在想下面的事情:

public static void AddOrUpdate<TKey, TValue>(this IDictionary<TKey, TValue> dictionary, TKey key, TValue value)
{
    // Initialize the Dictionary if null
    dictionary = dictionary ?? new Dictionary<TKey, TValue>();
    // Update or insert value
    dictionary[key] = value;
}

实际应用示例:

// null Dictionary
Dictionary<string, string> dict = null;
// Self-initializing
dict.AddOrUpdate("Key", "Value");

或者作为属性:

// Self-initializing
class.nullDict.AddOrUpdate("Key", "Value");

是否可以创建一个'自初始化'c# 6.0中的字典扩展方法

要使其工作,您必须通过ref传递参数,而这是不允许的。

this关键字修改静态方法的第一个参数时,它向编译器发出信号,表明该方法是扩展方法。不需要也不允许在扩展方法的第一个参数上使用修饰符。

您所要求的内容在如何获得更改原始对象的扩展方法中进行了讨论?结果是:在引用类型的情况下,您所能做的就是操作对象。你不能赋值它,因为那样你将处理一个本地副本,而不是最初传递给方法的对象:

public static void Foo(this Object bar)
{
    // assignment
    bar = new ...();
    // here you're NOT calling Baz() on the object passed into the method
    bar.Baz();
}

注意那些是引用类型语义。你甚至不能对值类型做任何有意义的事情:

public static void PlusOne(this int number)
{
    number++;
}

这将永远不会修改原始值,因为它们是根据定义按值传递的:这个扩展方法对调用它的值的副本进行操作。

话虽这么说,这更多的是关于期望的问题。有人在读这段代码吗?

Dictionary<string, string> dict = null;
dict.AddOrUpdate("Key", "Value");

将期望NullReferenceException(如果AddOrUpdate()Dictionary<TKey, TValue>的成员方法)或ArgumentNullException(在扩展方法的情况下),甚至编译器也会期望。

你认为你需要这个有一个潜在的原因。当然,实现"从扩展方法返回新的或更新的字典,并在每次修改时赋值"的答案是有效的,但会给您带来非常笨拙的语法:

Dictionary<string, string> dict = null;
dict = dict.AddOrUpdate("Key", "Value");

并且您只需要忘记不寻常的dict = 一次就可以在超出其使用范围的某个时刻获得NRE/ANE。如果你对函数式编程感兴趣,这可能没问题,但c#不是。

因此:确保在尝试添加键值对之前对字典进行初始化,这样所有这些不寻常的需求就消失了。它可能像这样简单:

Dictionary<string, string> dict = possiblyNullVariable ?? new Dictionary<string, string>();

我认为这对每个使用它的人来说都是非常困惑的,因为对空对象执行操作并不常见。

所以即使可能,我也宁愿使用

Dictionary<string, string> dict = new Dictionary<string, string>();

你可以,但是你必须将返回类型从void更改为Dictionay,这将是一个非常糟糕的设计。这样,每次使用扩展名时,调用者都必须执行赋值。

public static IDictionary<TKey, TValue> AddOrUpdate<TKey, TValue>(this IDictionary<TKey, TValue> dictionary, TKey key, TValue value)
{
    // Initialize the Dictionary if null
    if (dictionary == null)
        dictionary = new Dictionary<TKey, TValue>();
    // Update value if key already exists
    if (dictionary.ContainsKey(key))
        dictionary[key] = value;
    else
        // Insert value with the given key
        dictionary.Add(key, value);
    return dictionary;
}

我建议更改方法的签名:

// Let's return the dictionary (either passed or created) 
public static IDictionary<TKey, TValue> AddOrUpdate<TKey, TValue>(
    this IDictionary<TKey, TValue> dictionary, 
    TKey key, 
    TValue value) {
    IDictionary<TKey, TValue> result = dictionary;
    // Initialize the Dictionary if null
    if (result == null)
        result = new Dictionary<TKey, TValue>();
    // Update value if key already exists
    if (result.ContainsKey(key))
        result[key] = value;
    else
        // Insert value with the given key
        result.Add(key, value);
    return result;
}

Dictionary<string, string> dict = null;
dict = dict.AddOrUpdate("Key", "Value");

我认为你需要的是一个自初始化属性:

private Dictionary<string, string> dict;
public Dictionary<string, string> Dict => this.dict ?? (this.dict = new Dictionary<string, string>());

那么,无论何时使用Dict,它都保证被初始化