索引器是通过引用获取还是获取+设置? - c#

这是我的课:

class MyArray<T>
{
    private T[] data;
    public MyArray(int size)
    {
        data = new T[size];
    }
    public MyArray(in T[] array)
    {
        data = new T[array.Length];
        for (int i = 0; i < array.Length; i++)
            data[i] = array[i];
    }
    public T this[int i] //I am talking about this indexer
    {
        get => data[i];
        set => data[i] = value;
    }
}

我是否应该像上述那样定义索引器?

public ref T this[int i]
{
    get => data[i];
}

我应该选择哪种方法?据我所知,方法1允许您在设置值时执行其他代码,而方法2则允许您执行int.TryParse(str, out myArrayObj[i]);之类的操作

编辑:这个问题不仅适用于索引器,而且一般适用于任何属性。

参考方案

TL; DR如果需要设置器,则必须使用常规索引器,因为ref属性不能具有设置器。如果不需要设置器,那么我将始终在泛型类型参数的索引器/属性中指定ref关键字,因为它们可以是值类型。是否由ref访问它们取决于消费者。

如果类型参数是引用类型(一个类),则ref关键字没有任何好处,但是对于值类型却有所不同,因为可以直接访问它们而无需复制它们。因此,如果要访问数组中的原始值,则必须使用ref关键字。如果要访问传递给MyArray<T>类的数组中的值,则不应将值复制到其他私有数组,因为在这种情况下,您将获得私有数组中的值的副本。

以下示例显示ref的访问与常规访问有何不同:

[Fact]
public void ArrayTest()
{
    var structs = new[] {new MyStruct()};

    structs[0].Type++;

    ref var @struct = ref structs[0];
    @struct.Type++;

    // Test passes the value was incremented twice, because reference was used.
    structs[0].Type.Should().Be(2);
}

[Fact]
public void MyArrayTest()
{
    var structs = new MyArray<MyStruct>(new[] {new MyStruct()});

    // Compiler error, but was possible in earlier versions of C#
    // and would not modify the item in the array,
    // because value was copied before modification.
    // structs[0].Type++;

    var @struct = structs[0];
    @struct.Type++;

    // Value wasn't incremented, because it was copied on the stack.
    structs[0].Type.Should().Be(0);
}

[Fact]
public void MyRefArrayTest()
{
    var structs = new MyRefArray<MyStruct>(new[] {new MyStruct()});

    structs[0].Type++;

    ref var @struct = ref structs[0];
    @struct.Type++;

    // Test passes the value was incremented twice, because reference was used.
    structs[0].Type.Should().Be(2);
}

struct MyStruct
{
    public int Type { get; set; }
}

class MyArray<T>
{
    private T[] data;

    public MyArray(in T[] array)
    {
        data = new T[array.Length];
        Array.Copy(array, data, array.Length);
    }

    public T this[int i]
    {
        get => data[i];
        set => data[i] = value;
    }
}

class MyRefArray<T>
{
    private T[] data;

    public MyRefArray(in T[] array)
    {
        data = new T[array.Length];
        Array.Copy(array, data, array.Length);
    }

    public ref T this[int i]
    {
        get => ref data[i];

        // Compiler error, ref indexer cannot have setter.
        // set => data[i] = value;
    }
}

在Java中,执行“ ++++++++”表达式,编译器未报告任何错误并且可以正确执行? - java

我用eclipse编写了这段代码,用war写过,结果为3d。public static void main(String[] args) { double a = 5d + + + + + +-+3d; System.out.println(a); } 参考方案 您的表情可以改写为(5d) + (+ + + + +-+3d) 其中第一个+是应用于两个操作数的…

在Python和C++之间传输数据而无需写入Windows和Unix文件 - python

我有预先存在的python和C ++文件,其中python文件定义了许多点,而C ++代码利用其现有库进行了所需的计算。最终产品是C ++代码写入的文件。我正在寻找一种在python中获取2000点列表的方法,将其传递给函数,然后执行所有C ++代码并输出我需要的文件。其他注意事项。这必须是可以在Linux或Windows机器上工作的东西,并且最少安装新插件…

Java值加变量++ - java

考虑以下代码int val1 = 3; val1++; int val2 = val1++; System.out.println(val1); System.out.println(val2); Val1值= 5;Val2值= 4;为什么Val1的值是“ 5”?据我了解,应该为4,因为:在第1行,它的赋值为3,在第2行,通过val1 ++加上1,结果val…

如何锁定终端运行的perl,obj c,c++,python和ruby等脚本的源代码? - python

我想出售我在perl,obj c,c ++,python,ruby,bash,php等中制作的脚本等它们都在终端中运行。 (Linux)如何锁定源代码,以便无需人们访问源代码即可分发我的脚本..?换句话说,如何将在Terminal中运行的程序的源代码锁定,以便人们可以使用该程序(如果该代码已下载到他们的Linux机器上,但他们无法访问实际的源代码)?例:ex…

如何使用C#或C / C++在Windows 7中获取智能卡阅读器名称? - c#

我正在尝试制作一个将使用C .dll(不幸的是,.dll没有好的文档)来访问智能卡的C#程序。 .dll的功能之一使用读取器的名称作为参数。我的问题是我不知道该如何命名。在寻找答案之后,我在这里的示例中发现了与我所需要的东西类似的内容:http://msdn.microsoft.com/en-us/library/aa379803%28VS.85%29.as…