【问题标题】:C# - Good and flexible way to pass value types by reference?C# - 通过引用传递值类型的良好而灵活的方法?
【发布时间】:2013-04-19 17:21:33
【问题描述】:

我的问题,缩小到一个简单的解释,如下: 我有一门课需要处理一个可能会发生变化的数字(不改变它)。这个数字不一定来自另一个班级,它可以是任何东西。 但是我只想将它“给”一次类,而不是不断地调用更新方法或必须创建一个包装器(再次,正如我所说,这应该适用于任何类型的数字并且必须包装一切都有点不切实际)。

这里有一些代码,希望对你有帮助:

public class SimpleExample
{
    int value;
    public SimpleExample(int variableOfWhichINeedAReference)
    {
        //Of course this won't work, but I'll keep it simple.
        value = variableOfWhichINeedAReference; 
    }
    public void DisplayValue()
    {
        print(value);
    }
}
public class RandomClass
{
    int myValue = 10;
    SimpleExample s = new SimpleExample(myValue);

    public void WorkWithValue()
    {
        myValue++;
    }

    public void Display()
    {
        print(foo);
        print(bar);
        s.DisplayValue();
    }

}

现在,问题似乎很明显:如果我实例化一个 SimpleExample 并给它一个变量作为参数,它将获得它的值而不是对它的引用。 有没有一种足够简单的方法可以避免我创建包装器?谢谢。

【问题讨论】:

标签: c# variables reference


【解决方案1】:

制作一个非常简单的类:

class Ref<T>
{
    public T Value;
    public Ref<T>()
    {
    }
    public Ref<T>(T value)
    {
        this.Value = value;
    }
}

然后像这样使用它:

class A
{
    Ref<int> x;
    public A(Ref<int> x)
    {
        this.x = x;
    }
    public void Increment()
    {
        x.Value++;
    }
}

...

Ref<int> x = new Ref<int>(7);
A a = new A(x);
a.Increment();
Debug.Assert(x.Value == 8);

请注意,这里的Ref&lt;T&gt; 类是对的引用,而不是对变量的引用。如果您想引用变量,请使用Eric Lippert's solution(Filip 指出)。

【讨论】:

  • 请注意,这是创建一个包装类。 OP 特别说他不想那样做。
  • 另请注意,where T : struct 并不是真正需要的。这种类型对类和结构都非常有效,它对类和结构都有用,所以为什么要限制它。
  • @Servy 我明白,但是,我认为 OP 可能会发现这是解决他所遇到问题的最佳方法。因此,虽然它不是完全所要求的,但我认为它非常有用。它基本上提供了强类型的装箱(而不是object,它不提供)。
  • @TimothyShields 我同意这可能是解决 OP 真正问题的好方法,但事实仍然是,这不是问题的答案,因为问题 具体 禁止这个答案。
  • @Servy 我打赌 OP 更关心解决他的问题而不是处理 SO 法律主义......
【解决方案2】:

因此,您想要的不是 int,而是在某个时间点获取 int 的一种方式。有几种方法可以做到这一点,其中一种是让您的对象接受Func&lt;int&gt;。然后代码可以传入一个方法,该方法返回...的当前值,而不是创建 SimpleExample 时的值。使用 lambda 来关闭一个变量也让这件事变得更容易。

public class SimpleExample
{
    Func<int> func;
    public SimpleExample(Func<int> func)
    {
        this.func = func;
    }
    public void DisplayValue()
    {
        print(func());
    }
}
public class RandomClass
{
    int myValue = 10;
    SimpleExample s;

    public RandomClass()
    {
        s = new SimpleExample(() => myValue);
    }

    public void WorkWithValue()
    {
        myValue++;
    }

    public void Display()
    {
        print(foo);
        print(bar);
        s.DisplayValue();
    }
}

【讨论】:

  • 好问题,我的定义。不起作用 - 刚刚尝试过,你是对的:/
  • 如果您不想稍后获取 int 来修改它,您可以使用 Actions 而不是 Funcs,带有 0 个或多个参数并且没有返回类型/值。如果你想两者都做,Funcs 还处理参数(将它们的类型放在返回类型之前)。
【解决方案3】:

没有标准包装器可用于您所寻求的目的,尽管单元素数组可用于该目的。或者,可以定义一个简单的包装器类型:

public class ExposedValueHolder<T> { public T Value; } // Really simple class, eh?

然后使用ExposedValueHolder&lt;YourStructType&gt; 包装您的对象。通常不可能捕获作为任意ref 参数传递的东西,因为对象可能无限期地存在,但 byrefs(使用ref 参数时实际传递的东西)可能会在它们被传递给的函数后随时消失超出范围。

【讨论】:

  • @Filip:ExposedValueHolder 就像答案所暗示的那样,尽管我认为值得注意的是数组将是另一种选择。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-05-18
  • 2012-04-14
  • 1970-01-01
  • 1970-01-01
  • 2021-08-21
  • 2011-05-06
  • 1970-01-01
相关资源
最近更新 更多