Я могу использовать ссылку в функции C# как C++?

В C++ я могу сделать это:

 int flag=0,int1=0,int2=1;
 int &iRef = (flag==0?int1:int2);
 iRef +=1;

с эффектом, что int1 увеличен.

Я должен изменить некоторый более старый код c#, и было бы действительно полезно, если я мог бы сделать что-то подобное, но я думаю..., возможно, нет. Кто-либо?

6
задан Mark Byers 19 July 2010 в 20:44
поделиться

6 ответов

Вы можете сделать это - или, по крайней мере, что-то очень похожее на то, что вы хотите, но вероятно, лучше найти другой подход. Например, вы можете заключить целые числа в простой ссылочный тип.

Если вы все еще хотите это сделать, см. Класс Ref , опубликованный Эриком Липпертом здесь :

sealed class Ref<T>
{
    private readonly Func<T> getter;
    private readonly Action<T> setter;
    public Ref(Func<T> getter, Action<T> setter)
    {
        this.getter = getter;
        this.setter = setter;
    }
    public T Value { get { return getter(); } set { setter(value); } }
}

public class Program
{
    public static void Main()
    {
         int flag=0,int1=0,int2=1;

         Ref<int> iRef = (flag == 0 ?
            new Ref<int>(() => int1, z => { int1 = z; }) :
            new Ref<int>(() => int2, z => { int2 = z; }));

         iRef.Value += 1;

        Console.WriteLine(int1);
    }
}

Вывод:

1
5
ответ дан 8 December 2019 в 12:18
поделиться

Если все, что вам нужно, это изменить тип значения в функции, то передайте параметр с ключевым словом ref .

int i = 0;

void increment(ref int integer)
{
    integer++;
}

increment(ref i);

2
ответ дан 8 December 2019 в 12:18
поделиться

Не пугайтесь. Вы могли бы сделать это с помощью небезопасного кода и таких указателей:

    int flag=0,int1=0,int2=1;
    unsafe
    {
        int *iRef = (flag==0? &int1:&int2);
        *iRef +=1;
    }

(не говоря уже о том, что это хорошая идея или что-то в этом роде :))

1
ответ дан 8 December 2019 в 12:18
поделиться

В C # нет прямого эквивалента. Есть несколько вариантов -

Вы можете использовать небезопасный код и указатели, как предлагает dkackman .

Другой альтернативой является использование ссылочного типа (класса), который содержит значение. Например:

// Using something like
public class Wrapped<T> {
    public Wrapped(T initial) {
        this.Value = initial;
    }
    public T Value { get; set; }
}

// You can do:
bool flag=false;
var int1 = new Wrapped<int>(0);
var int2 = new Wrapped<int>(1);

Wrapped<int> iRef = flag ? int2 : int1;

iRef.Value = iRef.Value + 1;

Поскольку вы работаете со ссылками на класс, присвоение iRef копирует ссылку, и вышеуказанное работает ...

1
ответ дан 8 December 2019 в 12:18
поделиться

Вы можете использовать делегат действия следующим образом:

int flag = 0, int1 = 0, int2 = 0;
Action increment = flag == 0 ? (Action) (() => ++int1) : () => ++int2;
increment();
1
ответ дан 8 December 2019 в 12:18
поделиться

ОБНОВЛЕНИЕ: Обсуждаемая ниже функция была наконец добавлена ​​в C # 7.


Функция, которую вы хотите - сделать управляемым псевдонимы локальных переменных не поддерживаются в C #. Вы можете сделать это с помощью формальных параметров - вы можете сделать формальный параметр, который является псевдонимом любой переменной - но вы не можете сделать локальным , который является псевдонимом любой переменной.

Однако нет технических трудностей, которые мешают нам сделать это; система типов CLR поддерживает "локальные переменные ref".(Он также поддерживает возвращаемые типы ref, но не поддерживает поля ref.)

Несколько лет назад я фактически написал прототипную версию C #, которая поддерживала локальные переменные ref и возвращаемые типы ref, и она работала очень хорошо, так что у нас есть эмпирические доказательства что мы можем сделать это успешно. Однако маловероятно, что эта функция будет добавлена ​​в C # в ближайшее время, если вообще когда-либо. Подробнее см. http://ericlippert.com/2011/06/23/ref-returns-and-ref-locals/ .

Замечу, что на вашем месте я бы избегал этого на любом языке. Написание программ, в которых две переменные используют одно и то же хранилище, делает код трудным для чтения, понимания, изменения и сопровождения.

См. Также связанный с этим вопрос: Почему C # не поддерживает возврат ссылок?

7
ответ дан 8 December 2019 в 12:18
поделиться
Другие вопросы по тегам:

Похожие вопросы: