字典/通用委托集合

huangapple go评论72阅读模式
英文:

Dictionary/Collection of generic Delegates

问题

我想要拥有一组通用委托,每个委托都与不同的字符串键关联(类似于 Dictionary<string, delegate<T>>)。这些委托接受 T 并返回 T,这意味着返回类型与输入类型相同,有点像函数式的 map。这意味着每个单独函数的类型在编译时是已知的。我看不到为什么这不可能实现,但我还没有找到实现的方法。

我看到的主要解决方案是将 T 设为 object,然后每次都进行强制类型转换,但这很麻烦。另一个选择是使用动态类型,但这会损害类型安全性,并可能在长期内带来问题。还有可能实现一个自定义集合,但我不确定如何实现。

编辑:我想要一个通用的键值对,其中 T 对于每个键/对都是不同的类型。

英文:

I have want to have a collection of generic delegates, each tied to a different string key (something like a Dictionary&lt;string, delegate&lt;T&gt;&gt;). The delegates take in T and return T, meaning that the return type is the same as the input type, kind of like functional map. This means the type for each individual function is known at compile time. I see no reason why this shouldn't be possible but I haven't found a way to do it.

The main solutions I've seen are to make T an object and then cast it each time, but that's a hassle. Another option is to use dynamic, but that undermines type safety and might bring problems in the long run. There's also the possibility to implement a custom collection, but I'm not sure as to how.

Edit: I want a generic key-value pair where T is a different type for each key/pair.

答案1

得分: 1

你可以隐藏存储的细节,并在自定义类中提供自己的方法来设置和获取委托:

public class DelegateDictionary 
{
    private Dictionary<string, object> _entries = new Dictionary<string, object>();

    public void Add<T>(string key, Func<T, T> modifier)
    {
        _entries.Add(key, modifier);            
    }

    public Func<T, T> Get<T>(string key)
    {
        return _entries[key] as Func<T, T>;
    }
}

用法:

var dictionary = new DelegateDictionary();

dictionary.Add<string>("NameLowerCase", (name) => name.ToLower());
dictionary.Add<int>("AgeIncreaseByFive", (value) => value + 5);

var lowerCasedName = dictionary.Get<string>("NameLowerCase").Invoke("JUAN");
var numberIncreasedByFive = dictionary.Get<int>("AgeIncreaseByFive").Invoke(5);

Console.WriteLine($"JUAN => {lowerCasedName}");
Console.WriteLine($"5 => {numberIncreasedByFive}");

输出:

JUAN => juan
5 => 10

这只是一个过于简化的示例,但足以帮助你入门。

尽管如此,当我看到这样的代码时,通常意味着有必要退后一步重新考虑为什么需要这样做。

英文:

You can hide the details of storage and provide your own methods to set and get the delegates in a custom class:

public class DelegateDictionary 
{
    private Dictionary&lt;string, object&gt; _entries = new Dictionary&lt;string, object&gt;();

    public void Add&lt;T&gt;(string key, Func&lt;T, T&gt; modifier)
    {
        _entries.Add(key, modifier);            
    }

    public Func&lt;T, T&gt; Get&lt;T&gt;(string key)
    {
        return _entries[key] as Func&lt;T, T&gt;;
    }
}

Usage:

var dictionary = new DelegateDictionary();

dictionary.Add&lt;string&gt;(&quot;NameLowerCase&quot;, (name) =&gt; name.ToLower());
dictionary.Add&lt;int&gt;(&quot;AgeIncreaseByFive&quot;, (value) =&gt; value + 5);

var lowerCasedName = dictionary.Get&lt;string&gt;(&quot;NameLowerCase&quot;).Invoke(&quot;JUAN&quot;);
var numberIncreasedByFive = dictionary.Get&lt;int&gt;(&quot;AgeIncreaseByFive&quot;).Invoke(5);

Console.WriteLine($&quot;JUAN =&gt; {lowerCasedName}&quot;);
Console.WriteLine($&quot;5 =&gt; {numberIncreasedByFive}&quot;);

Output:

JUAN =&gt; juan
5 =&gt; 10

This is an overly simplified example but it should be enough to get you going.

All this being said, when I see something like this, it's usually a code smell worth taking a step back and rethinking why you need this in the first place.

答案2

得分: 0

我不确定这是可能的。泛型的整个要点是,当 T 在上下文中使用时,它在整个上下文中是相同的类型。通过将 T 作为字典的值类型的一部分,您将所有的值都链接到相同的上下文中,因此 T 的类型也是相同的。

英文:

I'm not sure this is possible. The whole point of generics is that when T is used in a context it is the same type for the whole of that context. By using T as part of the value type for the dictionary, you are linking all of the values into the same context, and thus a single type for T.

huangapple
  • 本文由 发表于 2023年6月30日 02:02:42
  • 转载请务必保留本文链接:https://go.coder-hub.com/76583568.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定