Переменная-член C # - PullRequest
       3

Переменная-член C #

6 голосов
/ 06 июня 2011

В C # есть ли способ сохранить ссылку как переменную-член в объекте (как указатель объекта в C ++), а не просто как параметр?

EDIT:Как сделать указатель или ссылку на объект как переменную-член?

Ответы [ 5 ]

12 голосов
/ 06 июня 2011

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

  • Используйте изменяемую оболочку типа
  • Используйте делегат, который вместо этого захватывает переменную
  • Переделайте код, чтобы он не требовался.

Трудно понять, какой из них наиболее подходит, не зная больше о том, чего вы пытаетесь достичь, но ref - это тупик.

4 голосов
/ 06 июня 2011

Если вы имеете в виду ref соглашение о передаче аргумента , то нет, вы не можете сохранить это.Из первой заметки на MSDN:

Не путайте концепцию передачи по ссылке с концепцией ссылочных типов.Эти две концепции не совпадают ...


Редактировать : на основе вашего обновленного вопроса C # имеет различную номенклатуру в отношении указателей и ссылок. A указатель в C # является небезопасной конструкцией , используемой для отчасти прямой ссылки на местоположение в памяти объекта.Я говорю несколько, потому что расположение памяти может меняться в зависимости от сборки мусора (если вы не исправите ее в памяти).

Ссылки в C # - это способ передачи и сохранения типов ссылок по умолчанию..Они похожи на указатели на других языках, но не совсем так.Однако соглашение о передаче аргументов по ссылке позволяет вам напрямую изменять объект, на который ссылается объект.

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

3 голосов
/ 06 июня 2011

Да, если это экземпляр ссылочного типа.И тогда это единственный способ сохранить его в другом классе:

class Bar { }

class Foo
{
    private Bar b; // b is a reference to a Bar
}

Нет, если речь идет о типе значения или ссылке на ссылку.

Везде, где C ++ использует указатели, вы увидите простые ссылки на объекты, как при построении деревьев или связанных списков.

class Element { ...; private Element _next; }
2 голосов
/ 09 января 2015

Для чего бы вы ни стояли, вы можете использовать массив размером 1 в качестве ссылки / указателя.Это дает более читаемый код, чем создание нового класса для переноса одного элемента типа значения.

public struct StructWithReferenceMember
{
    private int[] intStoredAsReference;

    public StructWithReferenceMember(int asValue, int asReference)
        : this()
    {
        IntStoredAsValue = asValue;
        intStoredAsReference = new int[] { asReference };
    }

    public int IntStoredAsValue { get; set; }
    public int IntStoredAsReference
    {
        get { return intStoredAsReference[0]; }
        set { intStoredAsReference[0] = value; }
    }
}

Подобный прием можно использовать для попытки крайне обескураженной практики использования изменяемых структур.

Затем используйте нотацию массива, чтобы «разыменовать» его.

public struct MutableStruct
{
    public int member;

    public MutableStruct(int value)
    {
        member = value;
    }
}
        ReferenceProperty<MutableStruct> referenceToValueType = new ReferenceProperty<MutableStruct>(new MutableStruct(3));
        Console.WriteLine("original value: " + referenceToValueType.PropertyAsValue.member.ToString());

        //referenceToValueType.PropertyAsValue.member = 4; // compiler error - cannot modify return value because it is not a variable
        MutableStruct copyOfStruct = referenceToValueType.PropertyAsReference[0]; // or referenceToValueType.PropertyAsValue
        copyOfStruct.member = 4;
        Console.WriteLine("original value after modifying copy: " + referenceToValueType.PropertyAsValue.member.ToString());

        referenceToValueType.PropertyAsReference[0].member = 5;
        Console.WriteLine("original value after modifying reference: " + referenceToValueType.PropertyAsValue.member.ToString());

original value: 3
original value after modifying copy: 3
original value after modifying reference: 5
1 голос
/ 06 июня 2011

Способ получения адреса переменной - это оператор &, аналогичный C ++. Как и в случае с C ++, вы можете сохранить адрес в виде указателя:

class Foo
{
    object* _objPtr;

    Foo(object obj)
    {
        unsafe
        {
           _objPtr = &obj;
        }
    }
}

Обратите внимание, что любой код, использующий оператор адреса (&) или указатели, должен находиться внутри метода, помеченного как небезопасный, или в блоке небезопасного кода. Это может быть полезно, если вы хотите повысить производительность, например, не выполняя проверку границ массива. Недостатком (помимо соображений безопасности) является то, что сборка должна быть полностью доверенной для ее выполнения.

Как указывалось, в C # вы на самом деле очень редко храните указатели, вместо этого вы храните ссылки, чтобы сборщик мусора мог работать должным образом. Убедитесь, что вам действительно нужны указатели в вашем коде, прежде чем их использовать!

Подробнее см .: http://msdn.microsoft.com/en-us/library/y31yhkeb.aspx

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...