是否有可能把这个类变成一个泛型类
本文关键字:泛型类 一个 有可能 是否 | 更新日期: 2023-09-27 18:07:05
有人能概括出这个问题底部列出的类别吗?我希望类不被锁定到类型为"GetStateDelegate"的委托,而是一个通用委托。这可能吗?
我已经尝试了一些事情,但是1)c#不喜欢这种类型的类声明:
public class StringToMethodMapper<T> where T: System.Delegate
这会产生"Cannot use System. "委托为类型参数约束"
如果你能给我一些提示,让我走上正轨,我会很感激的。此外,如果存在解决方案,我希望消费者尽可能少地受到更改的影响。例如,我宁愿不改变"Add(string, delegate)"的调用代码。
代码:
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>
,但这是不太可能的。
如果你愿意坚持使用一种类型的委托签名(例如:"总是三个参数和一个void返回"),那么您可以使用George的答案中的方法。如果它应该用于任何委托类型,那么您将坚持使用IL重写方法或放弃约束。
(根据评论编辑)
对于剩下的代码来说,这是对字典的一个非常缓慢的使用。目前你需要O(n)次查找。只需通过TryGetValue
使用正常的Dictionary
访问,但将StringComparer.OrdinalIgnoreCase
(或类似的东西)传递到构造函数中以获得不区分大小写的匹配。不可否认,这不会是一场比赛的开始……但是您当前的方法无论如何都不是确定的,因为您可能最终以"foo"answers"fo"作为字典中的键,它们都将匹配-因此您依赖于迭代器返回键的顺序。不是个好主意。
如果你真的需要StartsWith
行为,你可能想要调查实现一个trie -或者如果你对O(N)查找感到满意,我会保留一个List<KeyValuePair<string, TDelegate>>
,以明确你并没有真正使用它作为字典。
可能如下所示(键入时没有IDE)。显然,客户端将需要添加泛型参数,但我认为调用添加仍然工作。
public class StringToMethodMapper<T, TResult>
{
private Dictionary<string, Func<T, TResult>> _methods;
public StringToMethodMapper()
{
_methods = new Dictionary<string, Func<T, TResult>>();
}
public void Add(string key, Func<T, TResult> method)
{
_methods.Add(key, method);
}
internal virtual Func<T, TResult> GetMethodFor(string key)
{
foreach (var storedKey in _methods.Keys)
{
if (key.ToUpper().StartsWith(storedKey.ToUpper()))
{
return _methods[storedKey];
}
}
return null;
}
}
一种方法是将委托替换为接口
public interface IGetState
{
bool GetState(object someObject);
}
则可以使用此接口作为约束
public class StringToMethodMapper<T> where T: IGetState
{
...
}
你可以实现这个接口来做一些特别的事情,例如:
public class FileSystemState : IGetState
{
public bool GetState(object someObject)
{
// get state from the FS
}
}
和
var fileSystemMapper = new StringToMethodMapper<FileSystemState>();