如何修改方法内的装箱值类型

发布于 2024-07-08 02:41:16 字数 863 浏览 7 评论 0原文

我正在尝试构建一个库来简化 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

烟花肆意 2024-07-15 02:41:16

如果值在方法内部发生变化,您需要声明一个临时(object)变量以将(ref)传递给该方法,然后自己拆箱:

    int i = 3;
    //...
    object obj = i;
    Foo(ref obj);
    i = (int)obj;

请注意,这将不允许您在事件发生后更新值。 事件或回调之类的东西可能是将更改传递回调用者的另一种方法。

另请注意,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:

    int i = 3;
    //...
    object obj = i;
    Foo(ref obj);
    i = (int)obj;

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 course dynamic for late binding, as Jon notes]).

樱花落人离去 2024-07-15 02:41:16

你的方法无论如何都不会改变value - 为什么你要通过引用传递它? 这可能有道理,但对我来说并不是很清楚。 请注意,您提供的示例代码无论如何都不会编译,因为 ref 参数必须与参数完全相同的类型。

(另外,您是否知道 C# 4.0 和 .NET 4.0 将内置对后期绑定的支持?语言集成的版本可能比仅包含库的版本更容易使用。您确定值得花钱吗?此时在库上的时间?)

编辑:您提供的代码确实无法编译。 您不会对 ref 参数进行装箱,正是因为参数和参数类型必须完全相同。 下面是一些示例代码来证明这一点:

public class Test
{
    static void Main()
    {
        int i;
        Foo(ref i); // Won't compile - error CS1502/1503
    }

    static void Foo(ref object x)
    {
    }
}

如果您当前的代码正在编译,那么它就不是您在问题中提供的代码。 也许您有另一个接受 ref intAddParameter 重载?

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, as ref 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:

public class Test
{
    static void Main()
    {
        int i;
        Foo(ref i); // Won't compile - error CS1502/1503
    }

    static void Foo(ref object x)
    {
    }
}

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 accepts ref int?

似狗非友 2024-07-15 02:41:16

好的,感谢 Jon Skeet 的更正和 Mark Gravell 代码,我想出了这个界面:

        //This will be created with a factory
        IOperationInvoker invoker = new OperationInvoker(Activator.CreateInstance<MyLateBindingTestType>());

        int param1 = 2;
        object paramObj = param1;

        invoker.AddParameter(ref paramObj).Invoke("MulFiveRef");

        param1 = (int)invoker.Parameters[0];

并不完全像我想象的那样,但比我之前的界面更简单、更易读:

        IOperationInvoker invoker = new OperationInvoker(Activator.CreateInstance<MyLateBindingTestType>());
        int refValue = 10;
        object[] args = Args.Build(refValue);

        invoker.Call("MulFiveRef", Args.ByRefIndexs(0), args);

        refValue = (int)args[0];

非常感谢您的帮助:)

Ok, thanks to Jon Skeet corrections and Mark Gravell code, i've come up with this interface:

        //This will be created with a factory
        IOperationInvoker invoker = new OperationInvoker(Activator.CreateInstance<MyLateBindingTestType>());

        int param1 = 2;
        object paramObj = param1;

        invoker.AddParameter(ref paramObj).Invoke("MulFiveRef");

        param1 = (int)invoker.Parameters[0];

Is not exactly as I've imagined, but is way more simply and readable that my previous interface:

        IOperationInvoker invoker = new OperationInvoker(Activator.CreateInstance<MyLateBindingTestType>());
        int refValue = 10;
        object[] args = Args.Build(refValue);

        invoker.Call("MulFiveRef", Args.ByRefIndexs(0), args);

        refValue = (int)args[0];

Thank you very much for your help people :)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文