为什么 ref 参数类型与常规类型不同?
我了解如何在两种不同类型之间切换,但我的问题是;为什么类型级别存在这种差异?
我本以为它是 ParamterInfo 的属性
对象,而不是单独的特殊类型。
假设它在反射中呈现为单独的类型,因为它的内部就是这样,那么将其作为单独的类型有什么语言好处(我猜更容易的方法重载解析或其他什么)?
同样,为什么 ref
会产生不同的类型,而 out
却不会(我想不出 ref
是一个不同的类型的原因)单独的类型,不适用于 out
)?
I understand how to go between the 2 different types but my question is; why is this difference at the type level?
I would have thought it would be a property of the ParamterInfo
object, not separate special type.
Assuming it's presented as a separate type in reflection because that is how it is internally, what language benefits are there to having this as a separate type (I'm guessing easier method overload resolution or something)?
On a similar note, why does ref
make a distinct type but out
doesn't (I can't think of reasons for ref
being a separate type, that don't apply to out
)?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
ref
参数具有不同的类型,因为ref
类型在除参数之外的其他上下文中也是允许的和有用的。 C# 不允许,但其他语言(至少 C++/CLI)确实支持,例如引用类型的局部变量。这样的事情对于ref
有意义,但对于out
则没有意义。假装 C# 允许,您可以这样写(IL 支持):
这不是一个有用的示例,但在
ref
参数有用的相同情况下,使用带有ref
字段的辅助类或结构也很有用。ref
parameters have distinct types becauseref
types are also allowed and useful in other contexts than parameters. C# doesn't allow it, but other languages (at least C++/CLI) do support, for example, local variables of reference type. Such a thing makes sense forref
, but not forout
.Pretending C# allows it, you could write (it's supported by IL):
This isn't an example of when it's useful, but in the same situations where
ref
parameters are useful, it can also be useful to use a helper class or struct with aref
field.对
local
的赋值意味着local
标签在内存中的位置现在指向SomeStaticlyHeldString
所指向的同一对象。对
strParam
的赋值意味着参数在内存中使用ref
标签传递给方法的位置,现在指向与SomeStaticlyHeldString
相同的对象正在指着。获取
local.Length
查询local
指向的对象。获取strParam.Length
查询strParam
指向的变量所指向的对象。两者的行为确实非常不同,不仅在定义参数或局部变量时,而且在每次使用它们时。这种差异很大程度上是隐藏的,这使得它们更加不同,因为对它们的每次操作效果都不同。
如果我们有一种较低级的语言,除了局部变量、某种非局部堆上的对象以及指向这两者的指针之外什么都没有,那么
local
将是string*< 类型/code> 和
strParam
类型为string**
。这就是我们在 C 中执行类似操作的方式,以及我们如何在 C++ 中执行此操作,尽管它也有引用类型(尽管在 C++ 中,类型是引用类型更清楚地是其类型定义的一部分,并且它们有进一步的用途和改进)。 C# 在其语法中向我们隐藏了几乎所有这些内容。隐藏任何细节的好处总是有争议的,但在这种情况下,隐藏任何有用的东西并没有太多,所以人们很难批评它。The assignment to
local
means that the place in memory thatlocal
labels now points to the same object thatSomeStaticlyHeldString
was pointing to.The assignment to
strParam
means that the place in memory that the argument passed to the method usingref
labels, now points to the same object thatSomeStaticlyHeldString
was pointing to.Obtaining
local.Length
queries the object thatlocal
points to. ObtainingstrParam.Length
queries the object that the variable thatstrParam
points to, points to.The two are really behaving very differently, not just at the point the parameter or local is defined, but with every use of them. That the difference is largely hidden makes them all the more different, as every operation upon them differs in effect.
If we had a lower level language that had nothing but local variables, objects on some sort of non-local heap, and pointers to both of those, then
local
would be of typestring*
andstrParam
of typestring**
. This would be how we would do a similar sort of operation in C, and how we could do so in C++ though it also has reference types (though with C++ that a type is a reference type is more clearly part of its type definition, and they have further uses and refinements). C# hides almost all of this from us in its syntax. It's always debatable how beneficial any hiding of details is, but in this case there isn't much in the way of anything useful being hidden, so it's one that one would be hard-pressed to criticise.