【问题标题】:Saving a reference to a int保存对 int 的引用
【发布时间】:2011-02-25 18:27:24
【问题描述】:

这是我正在尝试做的一个非常简化的版本

static void Main(string[] args)
{
    int test = 0;
    int test2 = 0;
    Test A = new Test(ref test);
    Test B = new Test(ref test);
    Test C = new Test(ref test2);
    A.write(); //Writes 1 should write 1
    B.write(); //Writes 1 should write 2
    C.write(); //Writes 1 should write 1
    Console.ReadLine();
}
class Test
{
    int _a;
    public Test(ref int a)
    {
        _a = a; //I loose the reference here
    }
    public void write()
    {
        var b = System.Threading.Interlocked.Increment(ref _a);
        Console.WriteLine(b);
    }
}

在我的真实代码中,我有一个 int,它将被许多线程递增,但是在线程 a 调用的情况下,将指向它的参数传递给它并不容易 int(在实际代码中,这发生在 a IEnumerator)。所以一个要求是必须在构造函数中进行引用。此外,并非所有线程都指向同一个基 int,因此我也不能使用全局静态 int。我知道我可以将 int 封装在一个类中并传递该类,但我想知道这是否是执行此类操作的正确方法?

我认为可能是正确的方法:

static void Main(string[] args)
{
    Holder holder = new Holder(0);
    Holder holder2 = new Holder(0);
    Test A = new Test(holder);
    Test B = new Test(holder);
    Test C = new Test(holder2);
    A.write(); //Writes 1 should write 1
    B.write(); //Writes 2 should write 2
    C.write(); //Writes 1 should write 1
    Console.ReadLine();
}
class Holder
{
    public Holder(int i)
    {
        num = i;
    }
    public int num;
}
class Test
{
    Holder _holder;
    public Test(Holder holder)
    {
        _holder = holder;
    }
    public void write()
    {
        var b = System.Threading.Interlocked.Increment(ref _holder.num);
        Console.WriteLine(b);
    }
}

还有比这更好的方法吗?

【问题讨论】:

    标签: c# pass-by-reference


    【解决方案1】:

    基本上,答案是肯定的,你需要一门课。

    没有可以存储为字段的“对 int 的引用”的概念。在 C# 中,它仅限于参数。

    虽然有 unsafe 方式(指向 int 的指针,int*),但在这种情况下处理 GC 的复杂性使其不切实际且效率低下。

    所以你的第二个例子看起来不错。

    【讨论】:

      【解决方案2】:

      您不能存储对变量的引用,正是因为有人可以做您正在做的事情:获取对局部变量的引用,然后在局部变量的存储被回收后使用该引用。

      您将变量变成类字段的方法很好。做同样事情的另一种方法是让 getter 和 setter 委托给变量。如果委托在外部局部变量上关闭,则该外部局部将被提升到一个字段,使其生命周期比委托的生命周期长。

      【讨论】:

        【解决方案3】:

        不能将引用存储为字段。

        您需要将 int 保存在一个类中。

        【讨论】:

        • 这是否意味着我的第二个示例是“最佳实践”的方式?
        • 如果你需要这样做,可以,或者你可以切换到不安全的代码和大厅指针。
        • @Lase:但您必须“固定”目标。不太实用。
        猜你喜欢
        • 2014-04-11
        • 2021-11-23
        • 1970-01-01
        • 1970-01-01
        • 2015-12-13
        • 1970-01-01
        • 1970-01-01
        • 2018-05-05
        • 2016-12-05
        相关资源
        最近更新 更多