[英]C# struct by-ref
Is there any way in C# to be able to do this: C#中有什么方法可以做到这一点:
map.player.x = 5;
while keeping player
of type Point
(or silently convertible to one) and still be able to check the value for correctness when doing the assignment? 同时保持
Point
类型(或无声转换为一个)的player
,并且在进行分配时仍然能够检查该值的正确性?
To be clearer: 要更清楚:
Point
is a struct defined by the C#/.net standard libraries and is passed by value. Point
是C#/。net标准库定义的结构,并按值传递。 Point
's methods as call-throughs to Point
is long and tedious. Point
的方法,例如呼叫中指向Point
是漫长而乏味。 Point
will not allow the above. Point
的隐式覆盖只允许上述内容。 It would have to be written as (Point)(map.player).x
, which is clumsy. (Point)(map.player).x
,很笨拙。 If I understand you right, you seem to want to get some flexibility by defining type-conversions. 如果我理解正确,那么您似乎希望通过定义类型转换来获得一定的灵活性。 That won't go very far.
那不会太远。
Avoid mutable structs (value types). 避免使用可变结构(值类型)。
struct Point
is an unfortunate leftover from the old Win32 API. struct Point
是旧Win32 API的一个不幸残left。
So aim for map.player = new Point(5, map.player.y);
因此,瞄准
map.player = new Point(5, map.player.y);
No. Either player
is a variable , in which case you don't get any chance to verify the change during the assignment, or player
is a property , in which case the expression map.player
is categorized as a value and you're not allowed to set the x
part (as it would be usless). 号无论
player
是一个变量 ,在这种情况下,你没有得到任何机会,以验证分配过程中的变化,或player
是一个属性 ,在这种情况下,表达map.player
被归类为一个值 ,你不允许设置x
部分(这将是无用的)。
I would suggest you create a method, so you can call: 我建议您创建一个方法,以便可以调用:
map.SetPlayerX(5);
... or you make changing the x
value part of a larger operation which is owned by the Player
class. ...或者您可以更改
Player
类拥有的较大操作的x
值部分。 That's likely to be a more OO approach - usually if you find yourself wanting to do something like this, it's worth taking a look at the design and responsibilities. 这很可能是一种面向对象的方法- 通常,如果您发现自己想做这样的事情,那么值得研究一下设计和职责。
What about assigning both coordinates at the same time? 如何同时分配两个坐标呢?
map.player = new Point(5, 7);
Now you can have the validation logic inside of the player property. 现在,您可以在播放器属性中包含验证逻辑。
Do you really need to implement all the stuff of System.Drawing.Point
? 您真的需要实现
System.Drawing.Point
所有功能吗? It should not be all too difficult to implement your own version with only the things you really need. 仅使用您真正需要的东西来实现自己的版本并不难。 There is not much logic in
Point
. Point
没有太多逻辑。
Some people would suggest using a class type to hold the X and Y values. 有人建议使用类类型来保存X和Y值。 I am leery of that approach, and would suggest that in many cases the semantics obtained by exposing
player
as a field would be much cleaner (though I'm unclear why map
has a member called player
. If an map
is reference to MapType
, and instance of MapType
has a field of struct type player
, with a field x
of type integer, it is clear that a change to map.player.x
will affect one instance of MapType
. Also, saying map1.player = map2.player;
will copy the fields from map2.player
to map1.player
. By contrast, if player
were of a class type and one did map1.player = map2.player; map1.player.x = 5;
, that would affect both map1
and map2
. 我对这种方法持怀疑态度,并建议在许多情况下,将
player
公开为字段所获得的语义会更加简洁(尽管我不清楚为什么map
有一个名为player
的成员。如果map
引用了MapType
,并且MapType
实例具有一个结构类型为player
的字段,字段x
为整数类型,很明显,对map.player.x
的更改将影响一个MapType
实例。此外,说map1.player = map2.player;
将相比之下,将字段从map2.player
复制到map1.player
。相比之下,如果player
是类类型,并且一个人做了map1.player = map2.player; map1.player.x = 5;
那将同时影响map1
和map2
。
The question of whether to use a mutable struct versus a mutable class is pretty straightforward, but the notion of "If it's mutable make it a class" is just plain wrong. 关于使用可变结构还是可变类的问题很简单,但是“如果可变则使它成为一个类”的概念是完全错误的。 Simply ask yourself, given:
只需问问自己,给出:
thing1 = thing2; thing1.x = 5;
would you want the second statement to affect the value of thing2.x
? 您是否要第二条语句影响
thing2.x
的值? If yes, use a class. 如果是,请使用课程。 If no, use a struct.
如果否,请使用结构。
BTW, abother pattern to consider if you don't want your map type to expose player
as a field would be to have it expose an ActOnPlayer method: 顺便说一句,如果您不希望地图类型将
player
为字段,则需要考虑的另一种模式是使其显示ActOnPlayer方法:
public delegate ActionByRef<T>(ref T p); public delegate ActionByRef<T1,T2>(ref T1 p1, ref T2 p2); public void ActOnPlayer(ActionByRef<playerType> proc;) { proc(ref _player); } public void ActOnPlayer<T>(ActionByRef<playerType,T> proc, ref T param;) { proc(ref _player, ref param); } ... sample usage: map.ActOnPlayer((ref playerType it, ref int theParam) -> {it.x = theParam;}, someIntVariable);
Note that the latter approach would look something like using a closure, but unlike using a closure it would not generate any new temporary heap objects, and would thus not create any pressure on the garbage collector. 请注意,后一种方法看起来类似于使用闭包,但是与使用闭包不同,它不会生成任何新的临时堆对象,因此不会对垃圾收集器造成任何压力。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.