为什么在初始化Vector3时需要使用"new"关键字,但在初始化整数时不需要?

3
为什么当我初始化一个字符串或整数时,可以简单地这样做:
int number = 1;
string word = "word";

但如果我想初始化一个 Vector3,那么我必须这样做:

Vector3 coordinate = new Vector3(1f,1f,1f);

背景是我正在创建一个相当大的数组,并且每次都需要编写新的Vector3...,这变得非常繁琐:

Vector3[,] coordsList = new Vector3[11, 11]
{
    {new Vector3(-1.32f,1.32f), new Vector3(-1.08f,1.32f), new Vector3(-0.84f,1.32f), new Vector3(-0.6f,1.32f), new Vector3(-0.36f,1.32f), new Vector3(-0.12f,1.32f), new Vector3(0.12f,1.32f), new Vector3(0.36f,1.32f), new Vector3(0.6f,1.32f), new Vector3(0.84f,1.32f), new Vector3(1.08f,1.32f) },
    {new Vector3(-1.32f,1.08f), new Vector3(-1.08f,1.08f), new Vector3(-0.84f,1.08f), new Vector3(-0.6f,1.08f), new Vector3(-0.36f,1.08f), new Vector3(-0.12f,1.08f), new Vector3(0.12f,1.08f), new Vector3(0.36f,1.08f), new Vector3(0.6f,1.08f), new Vector3(0.84f,1.08f), new Vector3(1.08f,1.08f) },
    {new Vector3(-1.32f,0.84f), new Vector3(-1.08f,0.84f), new Vector3(-0.84f,0.84f), new Vector3(-0.6f,0.84f), new Vector3(-0.36f,0.84f), new Vector3(-0.12f,0.84f), new Vector3(0.12f,0.84f), new Vector3(0.36f,1.32f), new Vector3(0.6f,0.84f), new Vector3(0.84f,0.84f), new Vector3(1.08f,0.84f) },
    {new Vector3(-1.32f,0.60f), new Vector3(-1.08f,0.60f), new Vector3(-0.84f,0.60f), new Vector3(-0.6f,0.60f), new Vector3(-0.36f,0.60f), new Vector3(-0.12f,0.60f), new Vector3(0.12f,0.60f), new Vector3(0.36f,0.60f), new Vector3(0.6f,0.60f), new Vector3(0.84f,0.60f), new Vector3(1.08f,0.60f) },
    {new Vector3(-1.32f,0.36f), new Vector3(-1.08f,0.36f), new Vector3(-0.84f,0.36f), new Vector3(-0.6f,0.36f), new Vector3(-0.36f,0.36f), new Vector3(-0.12f,0.36f), new Vector3(0.12f,0.36f), new Vector3(0.36f,0.36f), new Vector3(0.6f,0.36f), new Vector3(0.84f,0.36f), new Vector3(1.08f,0.36f) },
    {new Vector3(-1.32f,0.12f), new Vector3(-1.08f,0.12f), new Vector3(-0.84f,0.12f), new Vector3(-0.6f,0.12f), new Vector3(-0.36f,0.12f), new Vector3(-0.12f,0.12f), new Vector3(0.12f,0.12f), new Vector3(0.36f,0.12f), new Vector3(0.6f,0.12f), new Vector3(0.84f,0.12f), new Vector3(1.08f,0.12f) },
    {new Vector3(-1.32f,-0.12f), new Vector3(-1.08f,-0.12f), new Vector3(-0.84f,-0.12f), new Vector3(-0.6f,-0.12f), new Vector3(-0.36f,-0.12f), new Vector3(-0.12f,-0.12f), new Vector3(0.12f,1.32f), new Vector3(0.36f,-0.12f), new Vector3(0.6f,-0.12f), new Vector3(0.84f,-0.12f), new Vector3(1.08f,-0.12f) },
    {new Vector3(-1.32f,-0.36f), new Vector3(-1.08f,-0.36f), new Vector3(-0.84f,-0.36f), new Vector3(-0.6f,-0.36f), new Vector3(-0.36f,-0.36f), new Vector3(-0.12f,-0.36f), new Vector3(0.12f,-0.36f), new Vector3(0.36f,-0.36f), new Vector3(0.6f,-0.36f), new Vector3(0.84f,-0.36f), new Vector3(1.08f,-0.36f) },
    {new Vector3(-1.32f,-0.6f), new Vector3(-1.08f,-0.6f), new Vector3(-0.84f,-0.6f), new Vector3(-0.6f,-0.6f), new Vector3(-0.36f,-0.6f), new Vector3(-0.12f,-0.6f), new Vector3(0.12f,-0.6f), new Vector3(0.36f,-0.6f), new Vector3(0.6f,-0.6f), new Vector3(0.84f,-0.6f), new Vector3(1.08f,-0.6f) },
    {new Vector3(-1.32f,-0.84f), new Vector3(-1.08f,-0.84f), new Vector3(-0.84f,-0.84f), new Vector3(-0.6f,-0.84f), new Vector3(-0.36f,-0.84f), new Vector3(-0.12f,-0.84f), new Vector3(0.12f,-0.84f), new Vector3(0.36f,-0.84f), new Vector3(0.6f,-0.84f), new Vector3(0.84f,-0.84f), new Vector3(1.08f,-0.84f) },
    {new Vector3(-1.32f,-1.08f), new Vector3(-1.08f,-1.08f), new Vector3(-0.84f,-1.08f), new Vector3(-0.6f,-1.08f), new Vector3(-0.36f,-1.08f), new Vector3(-0.12f,-1.08f), new Vector3(0.12f,-1.08f), new Vector3(0.36f,-1.08f), new Vector3(0.6f,-1.08f), new Vector3(0.84f,-1.08f), new Vector3(1.08f,-1.08f) },
};

但如果它是整数数组,那将会更加容易处理?是什么让Vector3需要使用new关键字,而整数或字符串不需要呢。


7
因为C#定义了常见类型的字面量,例如字符串和整数。 - juharr
3
也许现在对Unity来说这并没有多大的安慰,但C# 8通过其“目标类型的新表达式”功能(可在此处查看)确实解决了这种冗长的问题。 - Jonathon Chase
2
顺便提一下:使用矩形选择时,您真的不需要输入那么多...在进行选择并选择列时按住“Alt”键-输入将同时填充所有行... - Alexei Levenkov
2
看那个向量,它里面只有11个唯一的浮点数值。我会把它们硬编码成一个数组,并写几行代码来生成该向量数组本身。 - Nyerguds
更准确地说,struct System.Int32 没有非默认构造函数,因此您不能说 var i = new int(42);。我假设 Vector3 是一个结构体。当您说:new Vector3(-1.32f,1.32f), 时,您正在调用它的接受两个浮点数的构造函数。如果它是一个 struct,它有一个由系统编写的默认构造函数,只需将其所有成员初始化为它们的默认值。 - Flydog57
简单回答OP的问题是,int原始类型,而Vector3是复杂类型。对于这样大小的数组,您应该考虑通过编程生成它,特别是它是一个定义和常量网格模式。一个值的一维数组,您可以从嵌套循环中索引到它,这将是理想的。 - Immersive
4个回答

4
Vector3[][] list = new (float x, float y)[][]
{
    new[] { (1.5f, 3.4f), (1.5f, 6.8f) },
    new[] { (1.5f, 3.4f), (1.5f, 6.8f) },
    new[] { (1.5f, 3.4f), (1.5f, 6.8f) },
    new[] { (1.5f, 3.4f), (1.5f, 6.8f) },
}.Select(r => r.Select(v => new Vector3(v.x, v.y)).ToArray()).ToArray();

你可以使用值元组(现在在Unity 2018.3的最新版本中支持)以可读性更高和更少乏味的方式构建数据,然后你可以使用Select将它们转换为Vector3。
我认为大多数评论已经充分涵盖了关于这里新关键字的如何和为什么的问题。

2
< p > Vector3 需要使用 new 关键字的原因是,Vector3 是 Unity 内置的结构体,因此每次使用 new 关键字时,都会创建一个新的 Vector3 结构体实例,而对于 stringint 这些基本数据类型,则来自于 C#。

希望这有助于解释区别!


1
这不是一个 class 而是一个 struct。需要使用 new 来调用构造函数。 - Chris Dunaway
谢谢帮忙!我编辑了答案,使其更加正确。 - Eric Bishop

1

根据最近的评论,我想提出这个解决方案(通过扩展方法实现)。

var list  = new (float X, float Y, float Z)[2, 2]
{
    {(-1.32f, 0f, 1.32f), (-1.32f, 0f, 1.32f)},
    {(-1.32f, 0f, 1.32f), (-1.32f, 0f, 1.32f)}
};

Vector3[,] coordsList = list.ToVector3();

然后你可以使用扩展方法...
public static class Vector3Extensions
{
    public static Vector3[,] ToVector3(this (float X, float Y, float Z)[,] value)
    {
        int columnCount = value.GetUpperBound(0);
        int rowCount = value.GetLength(0);
        
        var result = new Vector3[rowCount, columnCount];
        for (int i = 0; i < rowCount; i++)
        {
            for (int j = 0; j < columnCount; j++)
            {
                var tuple = ((float X, float Y, float Z))value.GetValue(i, j);
                result[i, j] = tuple.ToVector3();
            }
        }
        
        return result;
    }
    
    public static Vector3 ToVector3(this (float X, float Y, float Z) value)
    {
        return new Vector3(value.X, value.Y, value.Z);
    }
}

当然,原始方案更有效率,但我当时不知道您正在使用Unity的struct。但是,这个解决方案仍然试图解决可读性和重复代码的问题。

原始帖子

我会假设你的问题目标是关于可读性和重构重复代码。你可以使用tuples隐式运算符使其更接近你想要的样子....

public class Vector3
{
    public Vector3(float x, float y)
    {
        this.X = x;
        this.Y = y;
    }
    
    public float X { get; set; }
    public float Y { get; set; }
    
    public static implicit operator (float X, float Y)(Vector3 value)
    {
        return (value.X, value.Y);
    }

    public static implicit operator Vector3 ((float X, float Y) value)
    {
        return new Vector3(value.X, value.Y);
    }
}

然后您可以像这样构建它...
Vector3[,] coordsList  = new Vector3[2, 2]
{
    {(-1.32f,1.32f), (-1.32f,1.32f)},
    {(-1.32f,1.32f), (-1.32f,1.32f)}
};

我本来想回答类似于这样的内容,但我认为他们正在使用Unity的Vector3结构体,而在C# 7中,目前无法为您未定义的数据类型创建自定义运算符。 - bug
@bug -- 继承对象不是一个选项吗? - Svek
2
@Svek 它是一个“struct”,所以不行。 - Jonathon Chase

0

你的坐标是一个XY镜像网格,这意味着你只有大约6个唯一的值。然而,为了让事情更容易,我们也会跟踪负数。

float[] values = new float[] { 
    1.32f,  1.08f,  0.84f,  0.6f,  0.36f,  0.12f, 
   -0.12f, -0.36f, -0.6f, -0.84f, -1.08f, -1.32f };

现在使用嵌套的for循环来填充你的coords数组:

Vector3[,] coordsList = new Vector3[11,11];

void Init() { 

    for ( int x = 0; x < coordsList.GetLength(0); x++) {
        for ( int y = 0; y < coordsList.GetLength(1); y++ ) {
            coordsList[x, y] = new Vector3(-values[x], values[y]);
        }
    }
}

如果你想要维护不同的坐标(即非网格映射),那么有其他方式来形成输入数据,但是转换为Vector3并不会有太大变化。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接