有人能够“通用化”此问题底部列出的课程吗?我希望该类不要被锁定为“ GetStateDelegate”类型的委托,而应被锁定为一般委托。那可能吗?
我尝试了几件事,但是1)C#不喜欢这种类型的类声明:
public class StringToMethodMapper<T> where T: System.Delegate
这将产生“不能使用System.Delegate作为类型参数约束”
提示使我走上正轨的提示表示赞赏。另外,如果存在解决方案,我希望消费者受更改的影响尽可能小。例如,我不想更改“ Add(字符串,委托)”的调用代码。
代码:
public delegate bool GetStateDelegate(object someObject);
public class StringToMethodMapper
{
private Dictionary<string, GetStateDelegate> _methods;
public StringToMethodMapper()
{
_methods = new Dictionary<string, GetStateDelegate>();
}
public void Add(string key, GetStateDelegate method)
{
_methods.Add(key, method);
}
internal virtual GetStateDelegate GetMethodFor(string key)
{
foreach (var storedKey in _methods.Keys)
{
if (key.ToUpper().StartsWith(storedKey.ToUpper()))
{
return _methods[storedKey];
}
}
return null;
}
}
最佳答案
就使其通用而言……好吧,这是有可能的。我有一个名为Unconstrained Melody的库,该库对具有委托约束的泛型使用IL重写-您可以在代码中使用相同的IL重写器。不过这很丑。基本上,IL支持所需的约束,但C#不支持。请注意,“它应该是从MulticastDelegate
派生但不包括MulticastDelegate
本身的类型”没有任何可能的限制,因此有人可以创建StringToMethodMapper<MulticastDelegate>
,但这很不方便。
如果您乐于坚持一种委托人签名(例如,“始终有三个参数且返回无效”),则可以使用George回答中的方法。如果它适用于任何委托类型,那么您将陷入IL重写方法或放弃约束的困境。
(根据评论进行编辑。)
就其余代码而言,这对字典的使用非常慢。目前,您有O(n)个查询。只需通过Dictionary
使用普通的TryGetValue
访问,但是将StringComparer.OrdinalIgnoreCase
(或类似方式)传递给构造函数即可获得不区分大小写的匹配。坦白说,那不会以“开始”匹配。但是您当前的方法还是不确定的,因为您可以在字典中以“ foo”和“ fo”作为键来结束,两者都将匹配-因此,您依赖于迭代器返回键的顺序。这不是一个好主意。
如果您确实需要StartsWith
行为,则可能想研究实现trie的方法-或者,如果您对O(N)查找感到满意,我会保留List<KeyValuePair<string, TDelegate>>
来表明您不是真正将其用作字典。
关于c# - 是否可以将此类变为通用类?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/7240841/