Как сохранить ссылку на целое число в С#?
Возможный дубликат:
Как назначить по ссылке на поле класса в С#?
Привет всем - расскажите, как это сделать? В принципе, мне нужен целочисленный ссылочный тип (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 во многих местах, только с ссылкой на желаемое целое число.
Ответы
Ответ 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 класс?
Просто интересно, если вы "изобретаете колесо"?