我经常遇到这种格式的代码..(我猜我在挑剔)我知道,classB可以标记为ref / out。我是从一个好的/最佳实践的观点来询问,还是我误解了引用/退出的观点。
我问的原因是,我发现有时候不知道我的对象中的属性是否会被更新,这让我感到困惑:/(意思是id需要深入研究方法以查看最新进展情况上)
public ClassB GetSomething()
{
var classB = new ClassB();
ClassA classA = .... // some code to get new obj
//from a glance i'm not ale to tell that classB gets updated/assigned to
this.DoSomething(classA , classB);
return classB;
}
private void DoSomething(ClassA classA, ClassB classB)
{
classB.Property = classA.something.Property;
}
答案 0 :(得分:3)
在您的示例中,假设ClassA
和ClassB
是引用类型,则classA
和classB
是按值传递的引用。如果在方法体内为它们分配新值,则在方法范围之外不会产生任何影响。例如;
private void Caller()
{
var classA = new ClassA();
var classB = new ClassB();
DoSomething(classA, classB);
// classA and classB still point to the instances from before the call to DoSomething()
}
private void DoSomething(ClassA classA, ClassB classB)
{
classA = null;
classB = null;
}
但是,您可以改变它们的属性,就像您在示例中所做的那样。
ref
和out
关键字用于表示参数是通过引用传递的,因此方法可以为参考参数指定新值。不同之处在于,在传递给方法之前必须为ref
参数指定参数,而在退出方法之前必须将out
参数指定给它们。
答案 1 :(得分:2)
你的ClassA
实际上是一个班级吗?
在这种情况下,不,您不需要ref
/ out
,此外,它会产生误导。
无论如何,类实例都是通过引用传递的。 ref
表示可以更改引用本身(out
表示将更改,并且该更改将在方法外部显示,对于您的代码不是这种情况:在您的示例中,仅更改此引用引用的对象。
在C#中,没有特殊的修饰符来控制方法是否可以更改对象的字段,调用其变异方法或以其他方式更改它。这些方法可以访问公开的所有内容。 (或者是受保护的,或者是私有的,如果在同一个类中。)并且可以在外部看到这些更改,因为两个代码都在查看相同的对象。
请注意,对于值类型(结构),它的工作方式会有所不同:对于结构体,被调用的方法不会将引用赋予该值类型,而是 copy 它。因此,对于struct \ s字段的任何更改(假设您有一个可变的结构,这本身就是坏的)在没有ref
的情况下将无法在外部看到。
答案 2 :(得分:2)
该代码很好 - classB已经是一个参考。如果您使用了ref,那么您将获得对引用的引用,这不是此处的目的。但它也使用它;考虑一下:
private void Foo()
{
object myObject = new object();
DoSomething(ref myObject);
}
private void DoSomething(ref object myObject)
{
myObject = new object();
}
当调用DoSomething时,它会更改Foo中myObject变量所指向的对象,以指向在DoSomething中创建的对象。
答案 3 :(得分:1)
严格来说,当您对对象(引用类型)进行更改时,不需要ref / out。我认为编写方法的清晰度是一个单独的问题,可以通过合适的设计模式等来解决。
答案 4 :(得分:1)
正如Cal279所提到的,你不需要ref修饰符,因为你实际上并没有改变classA指针的值,而是改变了引用类型的属性。
C#没有明确的语法来标记给定方法更改参数的状态,但是您可以通过适当地命名方法来自行完成:而不是DoSomething
,确保调用该方法{ {1}}或UpdateClassB
,甚至FillClassBFromClassA
。明确描述其作用的东西。