这是我的课:
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…