如何修改方法内的装箱值类型
我正在尝试构建一个库来简化 C# 中的后期绑定调用,但我在使用引用参数时遇到了麻烦。 我有以下方法来添加方法调用中使用的参数
public IInvoker AddParameter(ref object value)
{
//List<object> _parameters = new List<object>();
_parameters.Add(value);
//List<bool> _isRef = new List<bool>();
_isRef.Add(true);
return this;
}
,这不适用于值类型,因为它们被装箱为对象,因此不会被修改。 例如:
int param1 = 2;
object paramObj = param1;
//MulFiveRef method multiplies the integer passed as a reference parameter by 5:
//void MulFiveRef(ref int value) { value *= 5; }
fi.Method("MulFiveRef").AddParameter(ref paramObj);
那不行。 后期绑定调用成功,并且保存参数(_parameters)的内部列表确实被修改,但调用外部的值没有被修改。
有谁知道克服这个限制的简单方法? AddParameter 签名无法修改,与后期绑定调用一样,您无法提前知道参数的类型(无论哪种方式,您都可以在调用之前将调用的所有参数插入到对象数组中)
提前致谢。
I'm tring to build a library for simplifing late binding calls in C#, and I'm getting trouble tring with reference parameteres. I have the following method to add a parameter used in a method call
public IInvoker AddParameter(ref object value)
{
//List<object> _parameters = new List<object>();
_parameters.Add(value);
//List<bool> _isRef = new List<bool>();
_isRef.Add(true);
return this;
}
And that doesn't work with value types, because they get boxed as an object, thus they are not modified. E.g:
int param1 = 2;
object paramObj = param1;
//MulFiveRef method multiplies the integer passed as a reference parameter by 5:
//void MulFiveRef(ref int value) { value *= 5; }
fi.Method("MulFiveRef").AddParameter(ref paramObj);
That doesn't work. The late binding call is successful, and the inner List which holds the parameteres (_parameters ) does get modified, but not the value outside the call.
Does anyone knows a simple way to overcome this limitation?
The AddParameter signature cannot be modified, as with late binding calls, you cannot know in advance the Type of the parameters (and either way you insert all the parameters for a call inside an object array prior to making the call)
Thanks in advance.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
如果值在方法内部发生变化,您需要声明一个临时(
object
)变量以将(ref
)传递给该方法,然后自己拆箱:请注意,这将不允许您在事件发生后更新值。 事件或回调之类的东西可能是将更改传递回调用者的另一种方法。
另请注意,C# 4.0 有一些技巧仅在 COM 调用的上下文中帮助解决此问题(其中
ref 对象
非常常见[当然还有动态 用于后期绑定,如 Jon 所说])。
If the value is changing inside the method, you will need to declare a temp (
object
) variable to pass (ref
) to the method, and unbox it yourself afterwards:Note that this will not allow you to update the value after the event. Something like an event or callback might be an alternative way of passing changes back to the caller.
Note also that C# 4.0 has some tricks to help with this only in the context of COM calls (where
ref object
is so common [plus of coursedynamic
for late binding, as Jon notes]).你的方法无论如何都不会改变
value
- 为什么你要通过引用传递它? 这可能有道理,但对我来说并不是很清楚。 请注意,您提供的示例代码无论如何都不会编译,因为ref
参数必须与参数完全相同的类型。(另外,您是否知道 C# 4.0 和 .NET 4.0 将内置对后期绑定的支持?语言集成的版本可能比仅包含库的版本更容易使用。您确定值得花钱吗?此时在库上的时间?)
编辑:您提供的代码确实无法编译。 您不会对 ref 参数进行装箱,正是因为参数和参数类型必须完全相同。 下面是一些示例代码来证明这一点:
如果您当前的代码正在编译,那么它就不是您在问题中提供的代码。 也许您有另一个接受
ref int
的AddParameter
重载?Your method isn't changing
value
anyway - why are you passing it by reference? It may make sense, but it's not really clear to me. Note that the sample code you've provided wouldn't compile anyway, asref
arguments have to be exactly the same type as the parameter.(Also, are you aware that C# 4.0 and .NET 4.0 will have built-in support for late-binding? Chances are that the language-integrated version will be easier to use than a library-only one. Are you sure it's worth spending time on the library at this point in time?)
EDIT: The code you've provided really won't compile. You don't get boxing for
ref
parameters, precisely because the argument and parameter types have to be exactly the same. Here's some sample code to prove it:If your current code is compiling, then it's not the code you presented in the question. Perhaps you have another overload for
AddParameter
which acceptsref int
?好的,感谢 Jon Skeet 的更正和 Mark Gravell 代码,我想出了这个界面:
并不完全像我想象的那样,但比我之前的界面更简单、更易读:
非常感谢您的帮助:)
Ok, thanks to Jon Skeet corrections and Mark Gravell code, i've come up with this interface:
Is not exactly as I've imagined, but is way more simply and readable that my previous interface:
Thank you very much for your help people :)