C# 使用默认值初始化结构,返回null(自定义Matrix4结构)
我正在创建自己的Matrix4x4结构,但问题是,如果我在创建C# 使用默认值初始化结构,返回null(自定义Matrix4结构),c#,C#,我正在创建自己的Matrix4x4结构,但问题是,如果我在创建新Mat4x4()时没有给它任何参数值,那么它将为null,而不是将其设置为默认参数,在调试模式下查看时,它会临时在构造函数中设置值,但随后返回null 结构代码: public readonly struct Mat4x4 { public static Mat4x4 Identity { get; } = new Mat4x4(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
新Mat4x4()
时没有给它任何参数值,那么它将为null,而不是将其设置为默认参数,在调试模式下查看时,它会临时在构造函数中设置值,但随后返回null
结构代码:
public readonly struct Mat4x4
{
public static Mat4x4 Identity { get; } = new Mat4x4(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
private readonly double[] matrix;
public Mat4x4(double m00 = 1, double m01 = 0, double m02 = 0, double m03 = 0, double m10 = 0, double m11 = 1, double m12 = 0, double m13 = 0, double m20 = 0, double m21 = 0, double m22 = 1, double m23 = 0, double m30 = 0, double m31 = 0, double m32 = 0, double m33 = 1)
{
matrix = new double[] { m00, m01, m02, m03, m10, m11, m12, m13, m20, m21, m22, m23, m30, m31, m32, m33 };
}
public double this[int row, int column]
{
get
{
return (matrix[row * 4 + column]);
}
}
public override string ToString()
{
string str = $"[ {matrix[0]} , {matrix[1]} , {matrix[2]} , {matrix[3]} ]\n" +
$"[ {matrix[4]} , {matrix[5]} , {matrix[6]} , {matrix[7]} ]\n" +
$"[ {matrix[8]} , {matrix[9]} , {matrix[10]} , {matrix[11]} ]\n" +
$"[ {matrix[12]} , {matrix[13]} , {matrix[14]} , {matrix[15]} ]";
return str;
}
}
这将引发错误,因为matrix=null
:
Mat4x4 testMatrix = new Mat4x4();
Debug.Log(testMatrix.ToString());
但这将起作用,并将矩阵设置为更正默认值:
Mat4x4 testMatrix = new Mat4x4(m00:1);
Debug.Log(testMatrix.ToString());
我希望它工作的方式是,如果我不给它任何参数,它应该将值设置为与Identity
相同的值,而且我希望可以选择只设置所选值,如new Mat4x4(m02:2,m13:5)
,而其余值仍设置为Identity
编辑:
跳过使用double[]
public readonly struct Mat4x4
{
public static Mat4x4 Identity { get; } = new Mat4x4(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
public double M00 { get; }
public double M01 { get; }
public double M02 { get; }
public double M03 { get; }
public double M10 { get; }
public double M11 { get; }
public double M12 { get; }
public double M13 { get; }
public double M20 { get; }
public double M21 { get; }
public double M22 { get; }
public double M23 { get; }
public double M30 { get; }
public double M31 { get; }
public double M32 { get; }
public double M33 { get; }
public Mat4x4(double m00 = 0, double m01 = 0, double m02 = 0, double m03 = 0, double m10 = 0, double m11 = 0, double m12 = 0, double m13 = 0, double m20 = 0, double m21 = 0, double m22 = 0, double m23 = 0, double m30 = 0, double m31 = 0, double m32 = 0, double m33 = 0)
{
M00 = m00; M01 = m01; M02 = m02; M03 = m03;
M10 = m10; M11 = m11; M12 = m12; M13 = m13;
M20 = m20; M21 = m21; M22 = m22; M23 = m23;
M30 = m30; M31 = m31; M32 = m32; M33 = m33;
}
public double this[int row, int column]
{
get
{
return this[row * 4 + column];
}
}
public double this[int index]
{
get
{
switch (index)
{
case 0: return M00;
case 1: return M01;
case 2: return M02;
case 3: return M03;
case 4: return M10;
case 5: return M11;
case 6: return M12;
case 7: return M13;
case 8: return M20;
case 9: return M21;
case 10: return M22;
case 11: return M23;
case 12: return M30;
case 13: return M31;
case 14: return M32;
case 15: return M33;
default: return M00;
}
}
}
public override string ToString() =>
$"[ {M00} , {M01} , {M02} , {M03} ]\n" +
$"[ {M10} , {M11} , {M12} , {M13} ]\n" +
$"[ {M20} , {M21} , {M22} , {M23} ]\n" +
$"[ {M30} , {M31} , {M32} , {M33} ]";
}
var myMat=new Mat4x4()
将默认为0,0,0,0。。。对于标识矩阵var myMat=Mat4x4.identity
您可以声明自己的私有默认构造函数:
public readonly struct Mat4x4
{
private Mat4x4()
{
}
...
}
你不能这么做——至少不能用一种非常简单的方式
new Mat4x4
将始终将每个字段初始化为默认值-对于任何引用类型(包括数组),默认值为null
您可以通过矩阵
属性将空数组视为等同于标识
中的数组,该属性在代码中的任何地方都会使用
公共只读结构Mat4x4
{
公共静态Mat4x4标识{get;}=新的Mat4x4(1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1);
//仅存储-可能为空。
私有只读双[]矩阵;
//在任何地方使用它,它将永远不会为空。
私有双[]矩阵=>矩阵??Identity.Matrix;
公共Mat4x4(双m00=1,双m01=0,双m02=0,双m03=0,双m10=0,双m11=1,双m12=0,双m13=0,双m20=0,双m21=0,双m22=1,双m23=0,双m30=0,双m31=0,双m32=0,双m33=1)
{
矩阵=新的双[]{m00、m01、m02、m03、m10、m11、m12、m13、m20、m21、m22、m23、m30、m31、m32、m33};
}
public double this[int row,int column]=>矩阵[row*4+column];
公共重写字符串ToString()=>
$“[{Matrix[0]},{Matrix[1]},{Matrix[2]},{Matrix[3]}]\n”+
$“[{Matrix[4]},{Matrix[5]},{Matrix[6]},{Matrix[7]}]\n”+
$“[{Matrix[8]},{Matrix[9]},{Matrix[10]},{Matrix[11]}]\n”+
$“[{Matrix[12]},{Matrix[13]},{Matrix[14]},{Matrix[15]}]”;
}
请注意,属性仍然是私有的,并且需要是私有的-否则数组可能会发生变异。不,您不能在结构中声明无参数构造函数。是的,这是我已经尝试过的,可能应该提到的,但这不适用于结构。这正是我想要的工作方式,但是,这样做会带来额外的性能成本吗?我认为它本质上是在做一个
if matrix==null return Identity,else return matrix
检查每次你访问一个值吗?@PatrikFröhler:是的,它会这样做。这会影响性能,但这是否重要取决于您的应用程序。假设您的结构实际上有多个其他方法,在每种方法中,您可能希望在多次使用属性值之前获取属性值的本地副本。嗯,在这种情况下,我可能需要重新考虑一下,我目前正在重新编写旧的Matrix4,以尝试提高性能,我假设,当我想在一个方法中使用值时,必须复制一个矩阵,这也会带来一些性能成本。我可能会尝试不使用双数组并单独存储值,但访问变得很棘手,如果你有其他建议,我会很高兴听到它们。@PatrikFröhler:同样值得注意的是,虽然你的单位矩阵是乘法的自然默认值,对于其他事情,比如加法,它绝对不是一个好的默认值。这有点像将int
变量默认为1。您可能只想保持原样,并接受默认值无效。我创建了一个不使用数组的版本(请参见编辑),是的,它将默认为0,可能更好,然后,如果我想将其作为标识,我必须显式地将其设置为=Mat4x4.Identity
我查看了我的旧Matrix4x4结构,实际上我没有在任何点循环遍历这些值,所以我实际上不需要索引器。为什么结构
?使用class
和无参数构造函数。