在C类中使用ref#我想要一个我正在创建的类的链接列表。我希望类写入该列表(例如通过.addLast())。我应该使用ref关键字吗?我对在C#中在哪里使用ref和out关键字感到有点困惑,因为所有类都是在堆上动态分配的,我们实际上使用指针进行大多数操作。当然,out和ref关键字对基元和结构有意义。另外,如果我不直接发送列表,而是发送包含列表的类怎么办?(这是内部要求),我还需要使用ref吗?或者如果我在函数之间传递它,例如:voidA(refLinkedListlist){B(list);}voidB(refLinkedListlist){_myList=list;对于你正在做的事情,你不需要使用ref。如果您使用ref传递列表,则允许调用者更改您所引用的列表,而不仅仅是列表的内容。这是在C#中使用ref关键字的常见误解。它的目的是通过引用传递值或引用类型,并且仅在需要直接引用实际参数而不是参数副本(通过值或通过引用本身)的特定情况下才需要。在任何情况下都不应将引用类型与引用传递混淆。JonSkeet撰写了一篇关于C#中参数传递的优秀文章,其中对值类型、引用类型、按值传递、按引用传递(ref)和输出参数(out)进行了比较和对比。我建议你花一些时间仔细阅读这些内容,你的理解应该会更加清晰。引用该页面最重要的部分:值参数:默认情况下,参数是值参数。这意味着在函数成员声明中为变量创建了一个新的存储位置,它以您在函数成员调用中指定的值开始。如果更改该值,它不会更改调用中涉及的任何变量引用参数:引用参数不传递函数成员调用中使用的变量值——它们使用变量本身。不是在函数成员声明中为变量创建新的存储位置,而是使用相同的存储位置,因此函数成员中变量的值和引用参数的值将始终相同。引用参数需要ref修饰符作为声明和调用的一部分-这意味着当您通过引用传递某些内容时它总是很清楚。让我们看看前面的例子,只是将参数更改为引用参数:总结:阅读我的回复和JonSkeet的文章后,我希望您会发现在您的问题的上下文中使用ref关键字是不必要的。唯一需要在引用类型中使用ref的时候是在函数内部创建新对象时。示例#1:不需要ref关键字。//...列表myList=newList();填充列表(我的列表);//...voidPopulateList(ListAList){AList.Add("Hello");AList.Add("世界");}示例#2:ref关键字是必需的。//...列表myList;填充列表(参考我的列表);//...voidPopulateList(refListAList){AList=newList();AList.Add("你好");AList.Add("世界");在您发布的两个片段中,不需要通过ref传递列表。引用JonSkeet的话,对象引用是按值传递的。这意味着当方法将或可能更改对象引用并且您希望将此新引用返回给调用方法时,您可能希望引用引用类型。例如:voidmethodA(stringtest){test="HelloWorld";}voidmethodB(refstringtest){test="HelloWorld";}voidRunner(){stringfirst="string";方法A(第一);字符串第二个=“字符串”;方法B(参考第二);Console.WriteLine((first==second).ToString());//这会打印false}不,你不需要使用ref。LinkedList是一个对象,所以它已经是一个引用类型。参数列表是对LinkedList对象的引用。有关值类型的解释,请参阅此MSDN文章。值类型通常是您使用ref或out关键字的参数。您可能还希望通过ref传递引用类型。这将允许您指向另一个对象的引用。每当您传递对象o时,您实际上是在传递对该对象的引用。传递`refobjecto'时,您传递的是对引用的引用。这允许您修改引用。传递一个引用类型的参数也可以帮助你理解。我正在为像我这样习惯了C++的程序员添加这个答案。类、接口、委托和数组是引用类型,这意味着它们具有底层指针。普通函数调用按值复制此指针(引用),而按引用发送发送对此引用的引用://C#代码:voidFoo(ClassAinput)voidBar(ClassArefinput)//等效的C++代码:voidFoo(ClassA*input)voidBar(ClassA*&input)像int、double等原语。结构和字符串(字符串是这些的例外,但工作类似)分配在堆上,所以事情有点不同://C#代码:voidFoo(StructAinput)voidBar(StructArefinput)//等效的C++代码:voidFoo(StructAinput)voidBar(StructA&input)ref关键字需要在方法的声明中使用,调用它时,很明显它被引用了://C#code:voidFoobar(ClassBrefinput)...ClassBinstance=newClassB();Foobar(参考实例);//等效的C++代码:voidFoobar(ClassB*&input)...ClassBinstance*=newClassB();Foobar(实例);如前所述,请阅读本文以获取详细说明。它还解释字符串。有趣的是,通过引用调用使用底层指针,所以我们得到这段代码://C#code:voidFoo(ClassAinput){input=input+3;}voidBar(ClassArefinput){输入=输入+3;}//等效的C++代码:voidFoo(ClassA&input){input=input+3;}voidBar(ClassA*&input){*input=*input+3;}//等效的纯C代码:voidFun(ClassA*input){*input=*input+3;}voidFun(ClassA**input){*(*input)=*(*input)+3;这是一个粗略的等价物,但确实如此。我知道这是一个老问题,但在我看来,没有一个答案能给出一个很好的直接理由。在这种情况下,您不需要使用ref,原因如下。考虑这个函数:voidFoo(MyClassa1,refMyClassa2,outMyClassb1,intc1,MyStructd1,refMyStructd2){}现在调用这个函数MyClassa=newMyClass();MyClassb=nullintc=3;MyStructd=newMyStruct();Foo(a,refa,b,c,d,refd);这是你在函数中得到的:a2是指向实例化类a的指针;b1是指向b的指针,但具有必须在此函数内设置的额外检查-并且在设置之前不能使用;c1是变量c在内存中的副本;d1是结构d在内存中的副本;d2是结构d;:将a1设置为null不会将a设置为null。将a2设置为null将a2设置为null。需要设置b1。设置c1不会改变c。设置d1不会改变d。设置d2将改变d。这允许一些奇怪的事情,比如:voidFoo(MyClassx,refMyClassy){x=null;y.Bar("嗨");}称为:MyClassa=newMyClass();Foo(a,refa);您正在使用类,因此您的案例更像是函数调用中的变量a1。这意味着ref不是严格要求的。JonSkeet的文章对您帮助不大,因为他将IntHolder示例用作结构而不是类。Struct是一种类似int的值类型,必须以相同的方式处理。以上就是C#学习教程:使用ref以及C类#分享的所有内容。如果对你有用,需要进一步了解C#学习教程,希望大家多多关注。本文收集自网络,不代表立场。如涉及侵权请点击右侧联系管理员删除。如需转载请注明出处:
