我需要把一个Action<string>投给Action<object>。虽然这通常是类型不安全的,但在我的情况下,它总是用字符串调用的。我得到了一个错误:
Unable to cast object of type 'System.Action1[System.String]' to type 'System.Action1[System.Object]'.
有什么线索吗?反思是公平的游戏。将一个委托包装到另一个不是。
更新:我在Creating an performant open delegate for an property setter or getter创建了一个新的问题,更好地解释了我的问题,以及一个使用包装的解决方案,这是我想改进的。
发布于 2010-11-03 06:27:18
我知道您的文章指定在另一个委托中包装不是一个选项,但不幸的是,这确实是您在这里的最佳选择。CLR根本不允许在此方向上在委托之间进行强制转换。再多的反射也解决不了这个问题。你能进一步解释一下为什么这不是一种选择吗?
原因是它会产生类型安全问题,因为调用方可以将任何对象传递到Action<object>,而Action<string>只能处理字符串。即使您的代码只传入string,CLR也不能保证这一点,因此不允许不安全的转换。
我能想到的下一个最佳选择是将包装在Action<string>中的原始方法从接受string类型的参数更改为接受object的方法。然后让它手动验证类型是string。例如
// Original Version
void Method(string str) {
// Operate on the string
}
// Modified version
void Method(object obj) {
string str = (string)obj;
// operate on the string
}发布于 2010-11-03 04:42:11
首先,这不安全。可以接受任何字符串的东西不能(必然)接受任何对象。请考虑一个示例方法:
void method(String s)
{
s.Trim();
}显然,如果s是一个没有Trim的对象,这将失败。
从技术上讲,这意味着Action是T上的逆变体,您可以将Action<string>分配给假设的Action<SubclassString>引用,但是string不能被子类化。
确实,C#允许常规的不安全的强制转换(例如,object本身到string),而有InvalidCastException的风险。但是,他们选择不为不安全的委托转换实现基础设施。
编辑:我不知道在没有包装器的情况下有什么方法。
发布于 2016-08-12 22:19:46
抱歉,迟到了,但我今天想找个办法来做这件事,无意中发现了这篇文章。实际上,我找到的唯一简单的方法就是将Action<string>封装到一个新的Action<object>中。在我的例子中,我将我的操作推入并发字典,然后按类型检索它们。
实际上,我正在处理一个消息队列,其中可以定义操作以处理带有特定类型输入的消息。
ConcurrentDictionary<Type, Action<object>> _actions = new ConcurrentDictionary<Type, Action<object>>();
Action<string> actionStr = s => Console.WriteLine(s);
var actionObj = new Action<object>(obj => {
var castObj = (V)Convert.ChangeType(obj, typeof(V)); actionStr(castObj);
} );
_actions.TryAdd(typeof(string), actionObj);https://stackoverflow.com/questions/4084273
复制相似问题