mpen
mpen

Reputation: 282865

How to define a virtual getter and abstract setter for a property?

This is essentially what I want to do:

public abstract class Uniform<T>
{
    public readonly int Location;
    private T _variable;

    public virtual T Variable
    {
        get { return _variable; }
    }
}

public class UniformMatrix4 : Uniform<Matrix4>
{
    public override Matrix4 Variable
    {
        set
        {
            _variable = value;
            GL.UniformMatrix4(Location, false, ref _variable);
        }
    }
}

The getter for Variable will be the same across all derived classes, but the setter needs to be different.

In fact... I'd prefer not to have derived classes at all (it's only one function call that will differ for each type) but I can't think of how else to do it.


Edit: If it wasn't clear what the problem I'm having is, I'm getting a syntax error:

'UniformMatrix4.Variable.set': cannot override because 'Uniform.Variable' does not have an overridable set accessor

And I'm not sure how to create an "overridable set accessor"... virtual and abstract don't seem to be allowed on the setter.

Upvotes: 10

Views: 21861

Answers (3)

Ivo
Ivo

Reputation: 8352

You will need to do this:

public abstract class Uniform<T>
{
    public readonly int Location;

    public virtual T Variable
    {
        get; set;
    }
}

public class UniformMatrix4 : Uniform<Matrix4>
{
    public override Matrix4 Variable
    {
        get
        {
            return base.Variable;
        }
        set
        {
            base.Variable = value;
            GL.UniformMatrix4(Location, false, ref value);
        }
    }
}

As I understand, the behaviour will be the expected.

Hope it helps.

Upvotes: 7

It's not possible to do this in C#, but as a workaround you could do this. It would involve calling an abstract setter function which could be overridden by derived classes, while leaving the standard get intact. Would this work?

public abstract class Uniform<T>
{
    public readonly int Location;
    protected T _variable;

    public T Variable
    {
        get { return _variable; }
        set { SetVariable(value); } 
    }

    protected abstract void SetVariable(T value);
}

public class UniformMatrix4 : Uniform<Matrix4>
{
    public override void SetVariable(Matrix4x4 value)
    {
        _variable = value;
        GL.UniformMatrix4(Location, false, ref _variable);
    }
}

Upvotes: 14

Mike Nakis
Mike Nakis

Reputation: 61984

It is not possible to do this in C#. You have to add a setter to the base class, and make it throw an "Invalid Operation" exception.

Upvotes: 2

Related Questions