Подтвердить что ты не робот

Как сохранить ссылку на целое число в С#?

Возможный дубликат:
Как назначить по ссылке на поле класса в С#?

Привет всем - расскажите, как это сделать? В принципе, мне нужен целочисленный ссылочный тип (int * будет работать на С++)

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'
   }
 }

Нужно ли использовать бокс?

Edit: Возможно, я должен был быть более конкретным. Я пишу класс 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 во многих местах, только с ссылкой на желаемое целое число.

4b9b3361

Ответ 1

Вы не можете напрямую ссылаться на целое число, но вы можете сохранить ссылку на объект 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);
            }
    }
    }
}

Ответ 2

Вам не нужно иметь ссылку на целое число - просто поместите целое число внутри ссылочного типа - это почти то, что вы уже сделали. Просто измените эту строку:

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

Ответ 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();
    }
}

Я никогда не использовал указатели на С#, но, похоже, он работает. Я просто не знаю, каковы возможные побочные эффекты.

Ответ 4

Это не отвечает на ваш вопрос напрямую, но не можете ли вы использовать System.Collections.BitArray класс?

Просто интересно, если вы "изобретаете колесо"?