C#:指向多个整数的引用/指针数组
我想在数组中保存对许多短裤的引用。我以为我可以创建短裤,然后将它们添加到数组中。所以...每次引用的对象发生更改时,都会反映在数组中,反之亦然。经过一些试验后,我确信事实并非如此。事实上,看起来只是传递了值,而不是引用。
下面的代码创建两个 Short,将它们作为对象添加到数组中,然后更改原始 Short。然而,当访问数组中假定的引用的short时,它并没有改变,这让我相信它是一个全新的对象,与原始对象无关。
Console.WriteLine("Testing simple references:");
short v1 = 1;
short v2 = 2;
object[] vs = new object[2];
vs[0] = v1;
vs[1] = v2;
v1 = 1024;
v2 = 512;
Console.WriteLine(" v1: " + (short)vs[0]);
Console.WriteLine(" v2: " + (short)vs[1]);
我在这里误解了一些基本的东西,如果有人可以解释,并且也许向我指出一个可以实现我想要的解决方案,我将不胜感激。
I would like to hold references to a number of shorts in an array. I assumed I could just create the shorts and then add them to the array. So... every time the referenced object is changed, this is reflected in the array, and vice versa. Doing some trials convinced me that it does not quite work that way. In fact, it looks like the value is transferred but not a reference.
Below code creates two shorts, adds these to an array as objects, then changes the original short. However, when accessing the assumed referenced short in the array it has not changed, which leads me to believe that it is a wholly new object that has nothing to do with the original one.
Console.WriteLine("Testing simple references:");
short v1 = 1;
short v2 = 2;
object[] vs = new object[2];
vs[0] = v1;
vs[1] = v2;
v1 = 1024;
v2 = 512;
Console.WriteLine(" v1: " + (short)vs[0]);
Console.WriteLine(" v2: " + (short)vs[1]);
I am misunderstanding something fundamental here and would appreciate if someone could explain, and perhaps point me to a solution that would do what I want.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
C# 类型系统中有两种类型“值类型”和“引用类型”。
值类型按值复制;当你复制一个对象时,你会得到一个与原始对象无关的全新对象。
引用类型通过引用复制;当您复制一个时,您实际上是将引用复制到某个存储位置。您将获得两个引用,它们都引用一个对象。
短裤是价值类型。
如果您希望 Short 成为引用类型,那么您可以创建一个引用类型包装器:
就这样。
现在,您将获得对简短内容的引用访问权限,因为简短内容实际上存储在与类的 value 属性关联的字段中。如果你接着说:
你不会得到“3”——v2 现在指的是与 vs[1] 不同的对象。如果您真正想要捕获的是对变量的引用,那么您想要使用的就是闭包。
这里我们在数组中捕获知道如何获取和设置 v1 和 v2 的当前值的对象。
现在,如果您想要做的是直接为另一个变量创建一个别名,而不需要此对象,那么在 C# 中只有一种方法可以做到这一点:
现在“x”和“y”是同一变量的两个名称。然而,“为另一个变量创建别名”的概念仅在 C# 中当别名变量是方法的形式参数时才有效。一般情况下是没有办法做到的。
现在,理论上我们可以做你想要的事情。我们可以支持“ref locals”:
更新:我在这里讨论的“理论”功能已添加到 C# 7.0 中。
也就是说,rv1 成为 v1 的别名。 C# 不支持这一点,但 CLR 支持,因此我们可以支持它。但是,CLR 不支持创建“ref”元素类型的数组或存储引用的字段。所以从这个意义上说,你无法做你想做的事。
C# 确实支持一些特殊的“隐藏”功能,用于传递对象,这些对象的作用类似于对变量的引用,但比上面提到的“两个委托”引用更轻。然而,这些特殊功能仅适用于奇怪的互操作场景,我建议不要使用它们。 (再说一次,你不能创建一个存储类型引用的数组。)我认为我不会在这个答案中更多地讨论这些功能;你真的不想去那里,相信我。
There are two kinds of types in the C# type system "value types" and "reference types".
Value types are copied by value; when you copy one, you get a wholly new object that has nothing to do with the original.
Reference types are copied by reference; when you copy one, you are actually copying a reference to some storage location. You get two references that both refer to one object.
Shorts are value types.
If you want a short to be a reference type, then you could make a reference type wrapper:
And there you go.
Now, that will give you reference access to the short because the short is actually stored in the field associated with the value property of the class. If you then say:
you won't get "3" -- v2 now refers to a different object than vs[1]. If what you really want to capture is a reference to a variable then what you want to use is a closure.
Here we capture in the array objects which know how to get and set the current values of v1 and v2.
Now, if what you want to do is make an alias to another variable directly, without this object in the way, then there is only one way to do that in C#:
Now "x" and "y" are two names for the same variable. However, the concept of "make an alias to another variable" only works in C# when the aliasing variable is a formal parameter of a method. There is no way to do it in general.
Now, we could in theory do something like what you want. We could support "ref locals":
UPDATE: The "theoretical" feature I discuss here was added to C# 7.0.
That is, rv1 becomes an alias for v1. C# does not support this, but the CLR does and therefore we could support it. However, the CLR does not support making arrays of "ref" element type, or fields that store refs. So in that sense, you couldn't do what you want.
C# does support some special "hidden" features for passing around objects that act like references to variables but are lighter weight than the "two delegate" reference mentioned above. However, these special features are only for bizarre interop scenarios and I recommend against them. (And again, you can't make an array that stores typed references.) I don't think I'll talk about those features more in this answer; you really don't want to go there, believe me.
Short
是一个值类型,但是您试图使其表现得像引用类型。您可以创建一个带有
short
属性的类,然后使用该类的数组:您可以在那里做一些工作以使其更流畅(例如从
short
实现转换器> 到你的包装类并返回)。Short
is a value type, but you're trying to make it behave like a reference type.You can create a class with a
short
property and then use an array of that class:There's potentially some work you can do there to make it smoother (like implementing a converter from
short
to your wrapper class and back).short
类型是 值类型并且不像引用类型那样工作,引用类型的行为就像您期望的那样。当您将值类型分配给变量时,将分配其值,而不是其引用。vs[0]
将保存您分配给v1
的值的副本。如果您确实需要在更改原始值时更改数组中的值,则需要将您的 Short 包装在引用类型中。这是一个例子:
那么你可以这样使用它:
如果你改变
v1.Value
,那么shortArray[0].Value
也会改变。The
short
type is a value type and does not work like reference types which behaves like you are expecting your shorts to behave. When you assign a value type to a variable, its value is assigned, not its reference.vs[0]
will hold a copy of the value you assigned tov1
.If you really need to have the values in the array change when you change the original value, you need to wrap your short in a reference type. Here is an example:
Then you can use it like this:
If you change
v1.Value
, thenshortArray[0].Value
will also change.值类型之所以称为值类型,是因为它们在传递给方法或通过 = 运算符赋值时按值传递。
另一种(也是更正确的)看待它的方式是,shorts、ints 等是不可变的 =>它们无法改变。所以你基本上不能改变短路。如果您需要在某处更改 Short 类型的对象,则需要创建一个类来保存该对象,如下所示:
本质上,代码正在用新对象替换 Short 类型的对象。
顺便说一句,如果您需要包裹一条裸露短裤,那么您的设计很可能有问题。您要么应该已经使用一些更复杂的对象,要么应该以其他方式处理短裤数组。但我猜你只是在测试。
Value types are called value types because they are passed by value when passed to methods or assigned via the = operator.
Another (and more correct) way to look at it is that shorts, ints, etc. are immutable => they cannot be changed. So you basically cannot change a short. If you need an object of type short to change somewhere you need to create a class to hold this object like this:
Essentially the code is replacing the object of type short with a new object.
BTW chances are that there is something wrong with your design if you need to wrap a naked short. You either should be using some more complex object already or should be working with the array of shorts in some other way. But I guess you are just testing.
根本问题是
short
是一个结构体而不是一个对象。因此,基本上,short
数组实际上是一个short
数组,而不是对短对象的引用数组。要解决这个问题,您可以将短片“装箱”在课堂上(但这会很乏味)
尝试以下操作:
The fundamental problem is that
short
is a struct and not an object. So basically an array ofshort
is actually an array ofshort
and not an array of references to short objects.To solve the problem you can "box" the short in a class (but it's going to be tedious)
Try with the following:
如果您向类添加转换运算符,则可以透明地使用
ReferenceType
,就好像 float、int 等实际上是引用类型一样:通过使用
explicit
限定符而不是隐式
,如果您想让事情变得更清晰,但代价是有点冗长,您可以要求对这些转换进行强制转换。You can use
ReferenceType
transparently as if float, int etc. were actually reference types if you add a conversion operator to the class:By using the
explicit
qualifier instead ofimplicit
, you can require casts for these conversions, if you want to make things clearer at the expense of a little verbosity.