【问题标题】:How to store a reference to an integer in C#? [duplicate]如何在 C# 中存储对整数的引用? [复制]
【发布时间】:2017-08-14 18:34:28
【问题描述】:

可能重复:
How do I assign by “reference” to a class field in c#?

大家好 - 告诉我如何进行这项工作?基本上,我需要一个整数引用类型(int* 可以在 C++ 中工作)

class Bar
{
   private ref int m_ref;     // This doesn't exist

   public A(ref int val)
   {
      m_ref = val;
   }

   public void AddOne()
   {
      m_ref++;
   }
}

class Program
{
   static void main()
   {
      int foo = 7;
      Bar b = new Bar(ref foo);
      b.AddOne();
      Console.WriteLine(foo);    // This should print '8'
   }
 }

我必须使用拳击吗?

编辑: 也许我应该更具体。我正在编写一个 BitAccessor 类,它只允许访问单个位。这是我想要的用法:

class MyGlorifiedInt
{
   private int m_val;
   ...
   public BitAccessor Bits {
      return new BitAccessor(m_val);
   }
}

用法:

MyGlorifiedInt val = new MyGlorifiedInt(7);
val.Bits[0] = false;     // Bits gets a new BitAccessor
Console.WriteLine(val);  // outputs 6

要使 BitAccessor 能够修改 m_val,它需要对其进行引用。但我想在很多地方使用这个 BitAccessor,只需要引用所需的整数。

【问题讨论】:

  • 您的目标是什么?这基本上违背了托管代码的整个想法。如果您可以在生命周期与main 无关的其他类中存储对foo 的引用,那么当main 退出并且foo 所在的堆栈帧被破坏时会发生什么?
  • @tzaman,我的编辑是否明确了我的意图? @abatishchev - 我想,但没有一个答案完全符合我的要求。也许这是不可能的。
  • 为什么不安全的指针不能满足您的需求?你甚至提到如果这是在 C++ 中,指针就可以解决问题。
  • 这是stackoverflow.com/questions/2980463/… 的副本,请参阅我的回答,了解为什么不能将引用存储到字段中的变量以及绕过该限制的方法。
  • 是的,我想我明白你现在想要做什么了。我已经回答了这样做的方法。

标签: c# reference value-type


【解决方案1】:

这并不能直接回答你的问题,但你能不能不只使用System.Collections.BitArray 类?

只是想知道您是否在“重新发明轮子”?

【讨论】:

  • 请展示如何在这种情况下使用 BitArray
【解决方案2】:

您不能像这样直接存储对整数的引用,但可以存储对包含它的GlorifiedInt 对象的引用。在您的情况下,我可能要做的是将 BitAccessor 类嵌套在 GlorifiedInt 内(以便它可以访问私有字段),然后在创建时将其传递给 this 的引用,它可以然后使用 访问m_val 字段。这是一个示例,它可以满足您的需求:

class Program
{
    static void Main(string[] args)
    {
        var g = new GlorifiedInt(7);
        g.Bits[0] = false;
        Console.WriteLine(g.Value); // prints "6"
    }
}

class GlorifiedInt
{
    private int m_val;

    public GlorifiedInt(int value)
    {
        m_val = value;
    }

    public int Value
    {
        get { return m_val; }
    }

    public BitAccessor Bits
    {
        get { return new BitAccessor(this); }
    }

    public class BitAccessor
    {
        private GlorifiedInt gi;

        public BitAccessor(GlorifiedInt glorified)
        {
            gi = glorified;
        }

        public bool this[int index]
        {
            get 
            {
                if (index < 0 || index > 31)
                    throw new IndexOutOfRangeException("BitAcessor");
                return (1 & (gi.m_val >> index)) == 1; 
            }
            set 
            {
                if (index < 0 || index > 31)
                    throw new IndexOutOfRangeException("BitAcessor");
                if (value)
                    gi.m_val |= 1 << index;
                else
                    gi.m_val &= ~(1 << index);
            }
    }
    }
}

【讨论】:

  • 谢谢!这就是我一直在寻找的。你的 BitAccessor 看起来和我写的一样。唯一更好的是,能够将其应用于任何 Integer - 但如果没有参考,这是无法完成的。但是,您的解决方案适用于我的项目范围。
  • 你也可以添加这个: public static implicit operator GlorifiedInt(int v) { return new GlorifiedInt(v);这允许您编写例如GlorifiedInt a = 10;
【解决方案3】:

你没有指定你反对不安全的代码,所以这应该有效:

unsafe class Bar {
    private int* m_ref;

    public Bar(int* val) {
        m_ref = val;
    }

    public void AddOne() {
        *m_ref += 1;
    }
}

unsafe class Program {
    static void Main() {
        int foo = 7;
        Bar b = new Bar(&foo);
        b.AddOne();
        Console.WriteLine(foo);    // prints 8
        Console.ReadLine();
    }
}

我从未在 C# 中使用过指针,但它似乎可以工作。我只是不确定可能的副作用是什么。

【讨论】:

  • 您被明确禁止这样做。您必须从不像这样存储对堆栈指针的引用。如果在堆栈帧消失后指针仍然存在,就会发生不好的事情。这就是为什么这种模式首先在安全代码中是不合法的! 不安全的代码要求您知道所有可能的副作用是什么;这就是它不安全的原因。
  • 嗯,我每天都在学习新东西。感谢您的解释。 :)
【解决方案4】:

您不需要引用整数 - 只需将整数放入引用类型中即可 - 这几乎是您已经完成的工作。只需更改此行:

Console.WriteLine(foo);

到:

Console.WriteLine(bar.Value);

然后为类Bar添加一个适当的访问器,并删除编译错误(删除ref关键字)。

另一种方法是通过引用将整数传递给函数:

static void AddOne(ref int i)
{
    i++;
}

static void Main()
{
    int foo = 7;
    AddOne(ref foo);
    Console.WriteLine(foo);
}

输出:

8

【讨论】:

  • 这些都不是 OP 所要求的,这似乎是(如果我理解正确的话)某种方式将参考 存储到本地 int foo in @ 987654328@ 在Bar 对象中,这样Bar 实例上的other 方法调用会更改Mainfoo 的值。不确定这在 C# 中是否可行,无需进入不安全的代码......
  • @tzaman,第一个是 OP 要求的,行为方面;请记住,我们已经将Mainfoo 的使用替换为bar.Value。不过,这实际上只是手动拳击,OP 建议他不想要。
猜你喜欢
  • 2016-10-05
  • 2012-03-09
  • 2020-03-28
  • 1970-01-01
  • 2012-09-21
  • 2020-08-15
  • 2022-11-15
  • 1970-01-01
相关资源
最近更新 更多