3

我正在关注关于程序生成网格的教程,我想知道为什么当 List 只有一个 get 访问器时,可以将 .Add() 添加到作为类属性的 List 中。我是 C# 的新手,我在这里缺少什么?

例如,教程让用户编写这个类:

using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class MeshBuilder
{
    private List<Vector3> m_Vertices = new List<Vector3>();
    public List<Vector3> Vertices { get { return m_Vertices; } }

    private List<Vector3> m_Normals = new List<Vector3>();
    public List<Vector3> Normals { get { return m_Normals; } }

    private List<Vector2> m_UVs = new List<Vector2>();
    public List<Vector2> UVs { get { return m_UVs; } }

    private List<int> m_Indices = new List<int>();

    public void AddTriangle(int index0, int index1, int index2)
    {
        m_Indices.Add(index0);
        m_Indices.Add(index1);
        m_Indices.Add(index2);
    }

    public Mesh CreateMesh()
    {
        Mesh mesh = new Mesh();

        mesh.vertices = m_Vertices.ToArray();
        mesh.triangles = m_Indices.ToArray();

        //Normals are optional. Only use them if we have the correct amount:
        if (m_Normals.Count == m_Vertices.Count)
            mesh.normals = m_Normals.ToArray();

        //UVs are optional. Only use them if we have the correct amount:
        if (m_UVs.Count == m_Vertices.Count)
            mesh.uv = m_UVs.ToArray();

        mesh.RecalculateBounds();

        return mesh;
    }
}

然后我们编写另一个使用该类的脚本:

using UnityEngine;
using System.Collections;

public class ProcQuad : MonoBehaviour {

    float m_Width = 1;
    float m_Length = 1;

    // Use this for initialization
    void Start () {

        MeshBuilder meshBuilder = new MeshBuilder();

        //set up vertices and triangles
        meshBuilder.Vertices.Add (new Vector3(0.0f, 0.0f, 0.0f));
        meshBuilder.UVs.Add(new Vector2(0.0f, 0.0f));
        meshBuilder.Normals.Add(Vector3.up);

        meshBuilder.Vertices.Add(new Vector3(0.0f, 0.0f, m_Length));
        meshBuilder.UVs.Add(new Vector2(0.0f, 1.0f));
        meshBuilder.Normals.Add (Vector3.up);

        meshBuilder.Vertices.Add(new Vector3(m_Width, 0.0f, m_Length));
        meshBuilder.UVs.Add(new Vector2(1.0f, 1.0f));
        meshBuilder.Normals.Add(Vector3.up);

        meshBuilder.Vertices.Add (new Vector3(m_Width, 0.0f, 0.0f));
        meshBuilder.UVs.Add(new Vector2(1.0f, 0.0f));
        meshBuilder.Normals.Add(Vector3.up);

        meshBuilder.AddTriangle(0, 1, 2);
        meshBuilder.AddTriangle(0, 2, 3);


        MeshFilter filter = GetComponent<MeshFilter>();

        if (filter != null)
        {
            filter.sharedMesh = meshBuilder.CreateMesh();           
        }

    }

    // Update is called once per frame
    void Update () {

    }
}

那么为什么我们能够执行:

meshBuilder.Vertices.Add (new Vector3(0.0f, 0.0f, 0.0f));

当属性 Vertices 只有一个 get 访问器时,为什么它会修改私有字段 m_Vertices?

public List<Vector3> Vertices { get { return m_Vertices; } }

感谢您的洞察力。

如果有人对本教程感兴趣,我在这里找到了它:

http://jayelinda.com/wp/modelling-by-numbers-part-1a/

4

3 回答 3

3

由于该Add方法属于List<T>该类,因此您只需调用它是对列表对象的引用。有一个 getter 来提供引用就足够了,因为您不需要分配新列表,只需获取现有列表即可。

如果您想禁止添加,请将 getter 更改为 return AsReadOnly(),如下所示:

public List<Vector3> Vertices { get { return m_Vertices.AsReadOnly(); } }

请注意,调用Add()会编译,但由于在运行时列表是只读的,因此在Add()调用该方法时会引发异常。

于 2013-10-04T02:07:28.517 回答
1

你不能set列出的事实意味着这会给你一个编译错误:

meshBuilder.Vertices = new List<Vector3>();  //Not allowed! You're assigning to a list that you can't set

但是根据你那里的代码,它对get列表是完全合法的,m_Vertices并向它添加项目(就像任何其他的一样List),因为你没有ListVertices.

于 2013-10-04T02:06:46.747 回答
1

访问get器返回对List<T>. 在获得对它的引用之后,您可以调用它上的任何方法List<T>

缺少访问器会set阻止您另一个. 这是 List 或 Collection 属性的常见做法,以确保这些属性永远不会返回 nullList<T> List<T>

于 2013-10-04T02:07:55.570 回答