2011-12-31 3 views
5

Это, по сути, что я хочу сделать:Как определить виртуальный геттер и абстрактный сеттер для свойства?

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); 
     } 
    } 
} 

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

Фактически ... Я бы предпочел не иметь производные классы вообще (это только один вызов функции, который будет отличаться для каждого типа), но я не могу придумать, как это сделать.


Edit: Если бы не было ясно, что проблема у меня есть, я получаю ошибку синтаксиса:

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

И я не знаю, как создать «переопределяемый набор аксессуаров» ... virtual и abstract, похоже, не разрешены на сеттере.

+1

Что касается вашего редактирования: вот почему я дал ответ, который я дал. Я раньше задавался этой проблемой. –

ответ

8

Это невозможно сделать на C#, но в качестве обходного пути вы можете это сделать. Он включал бы вызов абстрактной функции сеттера, которая могла бы быть переопределена производными классами, оставив стандарт неизменным. Будет ли это работать?

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); 
    } 
} 
+0

Да, это сработает. За счет дополнительного вызова виртуальной функции. –

+0

Интересное решение! И это заставит производные классы реализовать сеттер. Не совсем чистый, но безопаснее. Мне это нравится! – mpen

+0

Если вы делаете это, 'Variable' больше не нужно виртуальным. – Gabe

2

Это невозможно сделать в C#. Вы должны добавить сеттер к базовому классу и заставить его выбросить исключение «Недействительная операция».

+0

Я думаю, что «NotImplementedException» имеет больше смысла, но кажется, что он работает сейчас: D – mpen

+0

Собственно, вы можете быть правы об исключении; например, это то, что класс ReadOnlyCollection бросает, если вы попытаетесь его модифицировать. –

6

Вам нужно будет сделать это:

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); 
     } 
    } 
} 

Как я понимаю, поведение будет ожидаемым.

Надеюсь, это поможет.

+1

'_variable' должен быть' value', так как вы удалили моего поддерживающего члена, но достаточно близко! Не думал, что я смогу сделать это без него. – mpen

+0

Я исправил это. Благодаря! – ivowiblo