【问题标题】:How to define a virtual getter and abstract setter for a property?如何为属性定义虚拟 getter 和抽象 setter?
【发布时间】:2012-01-31 05:33:38
【问题描述】:

这基本上就是我想要做的:

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 的 getter 在所有派生类中都是相同的,但 setter 需要不同。

事实上......我宁愿根本没有派生类(它只是一个函数调用,每种类型都会有所不同)但我想不出其他方法。


编辑:如果不清楚我遇到的问题是什么,我会收到语法错误:

“UniformMatrix4.Variable.set”:无法覆盖,因为“Uniform.Variable”没有可覆盖的集合访问器

而且我不确定如何创建“可覆盖的 set 访问器”... virtualabstract 似乎不允许在 setter 上使用。

【问题讨论】:

  • 关于您的编辑:这就是我给出我给出的答案的原因。这个问题我之前也很疑惑。

标签: c# properties virtual abstract


【解决方案1】:

在 C# 中无法执行此操作,但作为一种解决方法,您可以执行此操作。它将涉及调用一个抽象的 setter 函数,该函数可以被派生类覆盖,同时保持标准不变。这行得通吗?

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

【讨论】:

  • 是的,这行得通。以额外的虚函数调用为代价。
  • 有趣的解决方案!这将迫使派生类实现setter。不是很干净,但更安全。我喜欢!
  • 如果你这样做了,Variable 就不再需要是虚拟的了。
  • 是的,迈克,你是对的,它会导致额外的虚函数调用。这可以通过在覆盖的 SetVariable 函数上使用密封来缓解。我还从属性中删除了 virtual 所以感谢 Gabe 的评论。
  • Wh00ps,抱歉:是的,Variable 确实不必再是虚拟的了。所以,只有一个虚拟方法调用,所以性能与我的解决方案相同。而且更好。 +1。
【解决方案2】:

您需要这样做:

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

据我了解,行为将是预期的。

希望对你有帮助。

【讨论】:

  • _variable 应该是 value 因为你已经删除了我的支持成员,但足够接近!没想到没有一个我可以做到这一点。
【解决方案3】:

在 C# 中无法做到这一点。您必须向基类添加一个 setter,并使其抛出“无效操作”异常。

【讨论】:

  • 我认为NotImplementedException 更有意义,但它现在似乎正在工作:D
  • 实际上,您对异常的看法可能是正确的;例如,如果您尝试修改它,这就是 ReadOnlyCollection 类抛出的内容。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-03-04
  • 1970-01-01
  • 2012-09-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-04-09
相关资源
最近更新 更多