繁体   English   中英

在C#中实现行为类似于值类型的引用类型

[英]Implement in C# a reference type that behaves like a value type

我想在C#中实现3D Vector类型。 它将具有用于加,减,点积等的重载运算符。 使用模式要求它的行为类似于值类型-例如,我想要一个assigment语句来复制数据。 因此,出于这个(和其他)原因,似乎我应该使用一个结构。

但是我也想拥有一个UnitVector类型,以表示长度为1的向量。大概UnitVector应该继承自Vector。 但是继承仅在Vector和UnitVector是类而不是结构的情况下才有效。

我该怎么办? 有什么方法可以使Vector和UnitVector类的行为类似于值类型(就像字符串一样)? 还是有某种可能的方案,使Vector和UnitVector都独立实现某种IVector接口? 寻找建议的方法。

分配给该类型的引用后,将无法使C#引用创建副本。 因此,如果您要使用class UnitVector : Vector方法class UnitVector : Vector ,则可以进行赋值复制。

但是,@ ta.speot。已经为您指明了一个有用的方向:如果将Vector设置为不可变的类,则不必担心会对其进行复制-无论如何都无法更改。 如果还添加GetHashCode()Equals()以获取值相等语义,则这是一种非常好的值类型。 实际上,我更喜欢这样的类而不是结构,尽管它们最终在C#中输入了很多内容。

public class Vector3d
{
    public readonly double X, Y, Z;

    public Vector3d(double x, double y, double z)
    {
        X=x; Y=y; Z=z;
    }

    public double Dot(Vector3d other)
    {
        return X*other.X + Y*other.Y + Z*other.Z;
    }

    public UnitVector3d Normalize()
    {
        return UnitVector3d.FromVector(this);
    }

    /* More operators like Times and Length, plus Equals and GetHashCode here */
}

public class UnitVector3d : Vector3d
{
    private UnitVector3d (double x, double y, double z) : base(x, y, z)
    {
        /* General constructor. Private so it can only be called by trusted
           functions because it could be used to construct non-unit UnitVectors */
    }

    public static UnitVector3d FromVector(Vector3d vec)
    {
        Vector3d normalized = vec.Times(1.0/vec.Length());
        return new UnitVector3d(normalized.X, normalized.Y, normalized.Z);
    }
}

如果您想使用UnitVector子类,那么不变性也是一件非常好的事情。 为什么? 想象一下, Vector的组成可能会改变。 然后, UnitVector的组件将能够以相同的方式进行更改(否则将违反Liskov替换原理)。 但这意味着您可以更改UnitVector的方式来更改其长度。 哎呀。 这也称为Circle-Ellipse-Problem

使Vector不可变可以避免该问题。 UnitVector可能只是一个没有任何额外代码的子类,这些代码可用于表示已知长度为1的向量-您甚至可以覆盖在那里的Length函数以进行优化。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM