编码风格:ref / out变量,好/坏的做法?

时间:2012-11-19 15:21:22

标签: c# coding-style

我经常遇到这种格式的代码..(我猜我在挑剔)我知道,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;
    }

5 个答案:

答案 0 :(得分:3)

在您的示例中,假设ClassAClassB是引用类型,则classAclassB是按值传递的引用。如果在方法体内为它们分配新值,则在方法范围之外不会产生任何影响。例如;

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;
}

但是,您可以改变它们的属性,就像您在示例中所做的那样。

refout关键字用于表示参数是通过引用传递的,因此方法可以为参考参数指定新值。不同之处在于,在传递给方法之前必须为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。明确描述其作用的东西。