下面是一个结构实例方法的例子,它试图将只读引用返回给结构的实例字段:
struct Foo
{
internal int _x;
public ref readonly int MemberGetX() => ref _x;
// ^^^
// Error CS8170: Struct members cannot return 'this' or other instance members by reference
}
这会产生错误 CS8170 结构成员无法通过引用返回“this”或其他实例成员。然而,使用扩展方法做同样的事情不会产生错误:
static class FooExtensions
{
public static ref readonly int ExtensionGetX( this in Foo foo )
{
return ref foo._x;
}
}
相关问题的答案 Why can't a C# structure return a reference to its member field?讨论语言不允许第一种情况的原因,但考虑到这些原因,我不清楚为什么第二种情况是允许的。
更新:
这里有一个完整的例子,它不使用readonly,也显示了一个非扩展方法,并演示了用法:
struct Foo
{
internal int _x;
// Can't compile, error CS8170
// public ref int GetXRefMember() => ref _x;
public int X => _x;
}
static class FooExtensions
{
public static ref int GetXRefExtension( this ref Foo foo )
{
return ref foo._x;
}
public static ref int GetXRef( ref Foo foo )
{
return ref foo._x;
}
}
class Program
{
static void Main( string[] args )
{
var f = new Foo();
Console.WriteLine( f.X );
f.GetXRefExtension() = 123;
Console.WriteLine( f.X );
// You can also do it without using an extension method, but the caller is required to specify ref:
FooExtensions.GetXRef( ref f ) = 999;
Console.WriteLine( f.X );
/* Output:
* 0
* 123
* 999
*/
}
}
有趣的是,扩展方法默默地“添加”ref,当正常调用要求调用者显式添加 ref 到参数时,我假设要明确并防止错误。
最佳答案
我认为这包含在 ref-readonly proposal 中, 安全返回规则部分。
'this' is not safe to return from struct members
这个你已经知道了。您可以阅读更多关于为什么不允许的信息 here .简而言之 - 允许它“污染任何在本地值类型上调用的引用返回方法”,因此使所有 ref 从结构上的方法返回不是“安全返回”,因为它们可能包含引用到这个。
ref/in parameters are safe to return
instance struct fields are safe to return as long as the receiver is safe to return
这涵盖了静态方法的情况。 foo返回参数是安全的(因为 in ),因此 foo._x返回是安全的,作为本身可以安全返回的结构实例的字段。
a ref, returned from another method is safe to return if all refs/outs passed to that method as formal parameters were safe to return.
这可以防止上述静态方法出现问题。它使以下内容无效:
public static ref readonly int ExtensionGetX(in Foo foo) {
return ref foo._x;
}
static ref readonly int Test() {
var s = new Foo();
s._x = 2;
// fails to compile
return ref ExtensionGetX(s);
}
因为 s返回是不安全的,引用我们从 ExtensionGetX 得到的返回也不安全,因此我们不能将指向局部变量的指针泄漏到范围之外。
简而言之 - 它是允许的,因为它是安全的,并且没有禁止从结构成员方法返回 ref 到“this”的特定缺点。
更新。我认为更新您的问题不会改变我的答案。上述“安全返回”规则保持不变。你改变了in至 ref ,但是 ref参数也可以安全返回。它的实例字段也是如此。但是,如果您使返回的参数不安全:
public static ref int GetXRef(Foo foo)
{
return ref foo._x;
}
那么它不会编译。
您还认为(在评论中)“您不能将返回的引用存储为局部变量”,但事实并非如此:
ref int y = ref FooExtensions.GetXRef(ref f);
y = 10;
// print 10
Console.WriteLine(f.X);
所以,不管是否只读,in或 ref - 安全返回规则确保在这种情况下返回 ref struct 成员是安全的,同时允许返回对 this 的引用from struct local 方法会产生不良后果,强制将所有 struct 成员返回的所有 ref 值视为不安全返回。
如果 struct 成员可以将 ref 返回给 this 则不可能发生什么的小例子:
public ref int GetXRefMember(ref int y) => ref y;
static ref int Test(ref int y) {
var x = new Foo();
// safe to return, but won't be if ref to `this` can
// ever be returned from struct local method
return ref x.GetXRefMember(ref y);
}
关于c# - 为什么 C# 结构方法不能返回对字段的引用,但非成员方法可以?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50490143/
我正在学习如何使用Nokogiri,根据这段代码我遇到了一些问题:require'rubygems'require'mechanize'post_agent=WWW::Mechanize.newpost_page=post_agent.get('http://www.vbulletin.org/forum/showthread.php?t=230708')puts"\nabsolutepathwithtbodygivesnil"putspost_page.parser.xpath('/html/body/div/div/div/div/div/table/tbody/tr/td/div
总的来说,我对ruby还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用
类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc
我正在尝试设置一个puppet节点,但rubygems似乎不正常。如果我通过它自己的二进制文件(/usr/lib/ruby/gems/1.8/gems/facter-1.5.8/bin/facter)在cli上运行facter,它工作正常,但如果我通过由rubygems(/usr/bin/facter)安装的二进制文件,它抛出:/usr/lib/ruby/1.8/facter/uptime.rb:11:undefinedmethod`get_uptime'forFacter::Util::Uptime:Module(NoMethodError)from/usr/lib/ruby
我有一个模型:classItem项目有一个属性“商店”基于存储的值,我希望Item对象对特定方法具有不同的行为。Rails中是否有针对此的通用设计模式?如果方法中没有大的if-else语句,这是如何干净利落地完成的? 最佳答案 通常通过Single-TableInheritance. 关于ruby-on-rails-Rails-子类化模型的设计模式是什么?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.co
我想将html转换为纯文本。不过,我不想只删除标签,我想智能地保留尽可能多的格式。为插入换行符标签,检测段落并格式化它们等。输入非常简单,通常是格式良好的html(不是整个文档,只是一堆内容,通常没有anchor或图像)。我可以将几个正则表达式放在一起,让我达到80%,但我认为可能有一些现有的解决方案更智能。 最佳答案 首先,不要尝试为此使用正则表达式。很有可能你会想出一个脆弱/脆弱的解决方案,它会随着HTML的变化而崩溃,或者很难管理和维护。您可以使用Nokogiri快速解析HTML并提取文本:require'nokogiri'h
我想了解Ruby方法methods()是如何工作的。我尝试使用“ruby方法”在Google上搜索,但这不是我需要的。我也看过ruby-doc.org,但我没有找到这种方法。你能详细解释一下它是如何工作的或者给我一个链接吗?更新我用methods()方法做了实验,得到了这样的结果:'labrat'代码classFirstdeffirst_instance_mymethodenddefself.first_class_mymethodendendclassSecond使用类#returnsavailablemethodslistforclassandancestorsputsSeco
我正在使用的第三方API的文档状态:"[O]urAPIonlyacceptspaddedBase64encodedstrings."什么是“填充的Base64编码字符串”以及如何在Ruby中生成它们。下面的代码是我第一次尝试创建转换为Base64的JSON格式数据。xa=Base64.encode64(a.to_json) 最佳答案 他们说的padding其实就是Base64本身的一部分。它是末尾的“=”和“==”。Base64将3个字节的数据包编码为4个编码字符。所以如果你的输入数据有长度n和n%3=1=>"=="末尾用于填充n%
我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i
为什么4.1%2返回0.0999999999999996?但是4.2%2==0.2。 最佳答案 参见此处:WhatEveryProgrammerShouldKnowAboutFloating-PointArithmetic实数是无限的。计算机使用的位数有限(今天是32位、64位)。因此计算机进行的浮点运算不能代表所有的实数。0.1是这些数字之一。请注意,这不是与Ruby相关的问题,而是与所有编程语言相关的问题,因为它来自计算机表示实数的方式。 关于ruby-为什么4.1%2使用Ruby返