Есть ли способ сделать некоторую работу, когда переменная присваивается другой переменной (конструктор копирования?) - PullRequest
2 голосов
/ 22 апреля 2011
var abc = new MyObject();
var xyz = abc;

Насколько я понимаю, xyz и abc - это разные объекты, указывающие на одну и ту же информацию.

Есть ли способ подсчета ссылок?По сути, я хочу увеличить значение внутри объекта, когда происходит присвоение

Ответы [ 4 ]

2 голосов
/ 22 апреля 2011

Нет, xyz и abc различны ссылки на тот же объект .

И нет, вы не можете выполнять подсчет ссылок.

2 голосов
/ 22 апреля 2011

Нет.C # не является C ++;значение фактически не копируется в вставленный вами фрагмент кода (если MyObject не является типом значения).

1 голос
/ 22 апреля 2011

Единственный способ сделать это - использовать (неявные) перегрузки оператора приведения. Вероятно, это не то, что было задумано Эриком et.all, но это работает, если вы тщательно разрабатываете свои классы для этого.

В перегруженном операторе вы можете создать новый (левый) объект и обновить любые счетчики ссылок. Тем не менее, ясно, что это означает, что никаких других способов обойти эту схему не существует. То есть объект с правой стороны должен всегда иметь правильный тип. И использование 'var' было бы совершенно невозможно.

0 голосов
/ 22 апреля 2011

C # не допускает перегрузки оператора присваивания.Вы можете использовать обертки, которые увеличивают / уменьшают счетчик ссылок, но это не так красиво.Вот примерный набросок:

class RefCounted<T>
{
    private int refCount;
    public readonly T Obj;

    public RefCounted(T obj)
    {
        Obj = obj;
    }

    public void Get()
    {
        refCount++;
    }

    public void Release()
    {
        if (refCount > 0)
        {
            refCount--;
        }
    }
}

class Wrapper<T> : IDisposable
{
    private RefCounted<T> obj;
    private bool disposed = false;

    public Wrapper(RefCounted<T> o)
    {
        o.Get();
        obj = o;
    }

    public Wrapper<T> Copy()
    {
        return new Wrapper<T>(obj);
    }

    public static implicit operator T(Wrapper<T> wrapper)
    {
        return wrapper.obj.Obj;
    }

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    private void Dispose(bool disposing)
    {
        if (!this.disposed)
        {
            if (disposing)
            {
                obj.Release();
                obj = null;
            }
            disposed = true;
        }
    }
}

static class Wrapper
{
    public static Wrapper<T> New<T>(T obj)
    {
        return new Wrapper<T>(new RefCounted<T>(obj));
    }
}

Вот пример:

public class Task
{
    public int TaskId { get; set; }
    public int ParentId { get; set; }
}

...

var o = Wrapper.New(new Task() { TaskId = 1 });
var o1 = o.Copy();
var o2 = o1.Copy();
((Task) o1).TaskId = 3;
o2.Dispose();
o1.Dispose();
o.Dispose();

Вы также можете использовать using для определения объема, поскольку оболочка реализует IDisposable.

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