属性或索引器不能作为 out 或 ref 参数传递
我收到上述错误并且无法解决。 我用谷歌搜索了一下,但无法摆脱它。
场景:
我有类 BudgetAllocate
,其属性为 budget
,属于 double
类型。
在我的 dataAccessLayer 中,
在我的一个类中,我试图执行此操作:
double.TryParse(objReader[i].ToString(), out bd.Budget);
哪个抛出了此错误:
属性或索引器不能作为 out 或 ref 参数传递 编译时间。
我什至尝试过这个:
double.TryParse(objReader[i].ToString().Equals(DBNull.Value) ? "" : objReader[i].ToString(), out bd.Budget);
其他一切都工作正常并且存在层之间的引用。
I'm getting the above error and unable to resolve it.
I googled a bit but can't get rid of it.
Scenario:
I have class BudgetAllocate
whose property is budget
which is of double
type.
In my dataAccessLayer
,
In one of my classes I am trying to do this:
double.TryParse(objReader[i].ToString(), out bd.Budget);
Which is throwing this error:
Property or indexer may not be passed as an out or ref parameter at
compile time.
I even tried this:
double.TryParse(objReader[i].ToString().Equals(DBNull.Value) ? "" : objReader[i].ToString(), out bd.Budget);
Everything else is working fine and references between layers are present.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(10)
其他人已经为您提供了解决方案,但至于为什么这是必要的:属性只是方法的语法糖。
例如,当您使用 getter 和 setter 声明名为
Name
的属性时,编译器实际上会生成名为get_Name()
和set_Name(value) 的方法
。然后,当您读取和写入此属性时,编译器会将这些操作转换为对这些生成方法的调用。当您考虑到这一点时,就很明显为什么不能将属性作为输出参数传递 - 您实际上会传递对方法的引用,而不是对
对象的引用< /s> 一个变量,这是输出参数所期望的。索引器也存在类似的情况。
Others have given you the solution, but as to why this is necessary: a property is just syntactic sugar for a method.
For example, when you declare a property called
Name
with a getter and setter, under the hood the compiler actually generates methods calledget_Name()
andset_Name(value)
. Then, when you read from and write to this property, the compiler translates these operations into calls to those generated methods.When you consider this, it becomes obvious why you can't pass a property as an output parameter - you would actually be passing a reference to a method, rather than a reference to
an objecta variable, which is what an output parameter expects.A similar case exists for indexers.
这是一个抽象漏洞的例子。属性实际上是一种方法,索引器的 get 和 set 访问器被编译为 get_Index() 和 set_Index 方法。编译器很好地隐藏了这一事实,例如,它会自动将对属性的赋值转换为相应的 set_Xxx() 方法。
但是,当您通过引用传递方法参数时,这就出问题了。这要求 JIT 编译器传递一个指向所传递参数的内存位置的指针。问题是,没有一个,分配属性的值需要调用 setter 方法。被调用的方法无法区分传递的变量与传递的属性之间的区别,因此无法知道是否需要方法调用。
值得注意的是,这实际上可以在 VB.NET 中运行。例如:
VB.NET 编译器通过自动为 Run 方法生成此代码(以 C# 表示)来解决此问题:
这也是您可以使用的解决方法。不太清楚为什么 C# 团队不使用相同的方法。可能是因为他们不想隐藏潜在昂贵的 getter 和 setter 调用。或者,当设置器具有更改属性值的副作用时,您将得到完全无法诊断的行为,它们将在赋值后消失。 C# 和 VB.NET 之间的经典区别,C# 是“没有惊喜”,VB.NET 是“如果可以的话,让它工作”。
This is a case of a leaky abstraction. A property is actually a method, the get and set accessors for an indexer get compiled to get_Index() and set_Index methods. The compiler does a terrific job hiding that fact, it automatically translates an assignment to a property to the corresponding set_Xxx() method for example.
But this goes belly up when you pass a method parameter by reference. That requires the JIT compiler to pass a pointer to the memory location of the passed argument. Problem is, there isn't one, assigning the value of a property requires calling the setter method. The called method cannot tell the difference between a passed variable vs a passed property and can thus not know whether a method call is required.
Notable is that this actually works in VB.NET. For example:
The VB.NET compiler solves this by automatically generating this code for the Run method, expressed in C#:
Which is the workaround you can use as well. Not quite sure why the C# team didn't use the same approach. Possibly because they didn't want to hide the potentially expensive getter and setter calls. Or the completely undiagnosable behavior you'll get when the setter has side-effects that change the property value, they'll disappear after the assignment. Classic difference between C# and VB.NET, C# is "no surprises", VB.NET is "make it work if you can".
您不能使用
某些变量替换 bd.Budget 。
you cannot use
replace bd.Budget with some variable.
可能感兴趣 - 您可以编写自己的:
Possibly of interest - you could write your own:
将 out 参数放入局部变量中,然后将该变量设置为
bd.Budget
:更新:直接来自 MSDN:
Place the out parameter into a local variable and then set the variable into
bd.Budget
:Update: Straight from MSDN:
这是一篇非常古老的帖子,但我正在修改已接受的帖子,因为有一种我不知道的更方便的方法。
它被称为内联声明,并且可能一直可用(如在 using 语句中),或者在这种情况下可能已使用 C#6.0 或 C#7.0 添加了它,不确定,但无论如何都像魅力一样:
此使用的 Inetad
:
This is a very old post, but I'm ammending the accepted, because there is an even more convienient way of doing this which I didn't know.
It's called inline declaration and might have always been available (as in using statements) or it might have been added with C#6.0 or C#7.0 for such cases, not sure, but works like a charm anyway:
Inetad of this
use this:
所以预算是一种财产,对吗?
而是首先将其设置为局部变量,然后将属性值设置为该变量。
So Budget is a property, correct?
Rather first set it to a local variable, and then set the property value to that.
我遇到了同样的问题(5 分钟前),我使用带有 getter 和 setter 的旧样式属性解决了这个问题,它们使用变量。
我的代码:
所以,我只是使用了 bigField 变量。我不是程序员,如果我误解了这个问题,我真的很抱歉。
I had the same problem (5 minutes ago) and I solved it using old style properties with getter and setter, whose use variables.
My code:
So, I just used bigField variable. I'm not the programmer, if I misunderstood the question, I'm really sorry.
通常,当我尝试执行此操作时,这是因为我想设置我的属性或将其保留为默认值。借助这个答案和
dynamic
类型,我们可以轻松创建一个字符串扩展方法来保持它一字排开,简单。像这样使用;
可选
顺便说一句,如果这是一个
SQLDataReader
,您还可以使用GetSafeString
扩展来避免读取器出现空异常。像这样使用;
Usually when I'm trying to do this it's because I want to set my property or leave it at the default value. With the help of this answer and
dynamic
types we can easily create a string extension method to keep it one lined and simple.Use like so;
Optional
On a side note, if that's an
SQLDataReader
you may also make use ofGetSafeString
extension(s) to avoid null exceptions from the reader.Use like so;
如果您使用“ref”关键字,请不要使用“properties”,它会在编译时带来很多问题和错误。保持老派,只使用简单明了的字段。所以这就是答案:
if you using "ref" keyword please don't use "properties" it brings a lot of problems and errors in compile time. keep it old school and just use plain and simple fields. so this is the answer: