0

.NETでクラスを作成すると、それは参照型になります。この例では、SomeMethod内でMyClassの名前を設定しています。Mainメソッド内では、渡されるパラメーターが参照型であるため、SomeMethodからの戻り値を実際に割り当てる必要はありません。mainメソッドのインスタンスに、新しく更新された名前「John」を付けたいのですが、そうです。

更新されたプロパティをメインのオリジンインスタンスに再割り当てするためにこれが必要ではない場合でも、読みやすくするために、とにかく戻り値を割り当て先に戻すことがよくあります。私の仮定では、コンパイラはMainメソッド内にMyClassの新しい参照を再作成しないほど賢いです。本当?または、コンパイラは実際に新しい参照を作成し、戻り値を割り当てるときに更新された値を指しますか?

//My class will be a reference type
public class MyClass 
{
    public int ID { get; set; }
    public string name { get; set; }
}

public class Main
{
    //Main method of application
    public void Main()
    {
        MyClass myClass = new MyClass();
        //return value back to itself
        myClass = SomeMethod(myClass);
    }

    public MyClass SomeMethod(MyClass myClass)
    {
        myClass.name = "John";
        return myClass;
    }
}

これがILです

    instance void Main1 () cil managed 
{
    // Method begins at RVA 0x207c
    // Code size 15 (0xf)
    .maxstack 2
    .locals init (
        [0] class Test.MyClass myClass
    )

    IL_0000: newobj instance void Test.MyClass::.ctor()
    IL_0005: stloc.0
    IL_0006: ldarg.0
    IL_0007: ldloc.0
    IL_0008: call instance class Test.MyClass Test.Main::SomeMethod(class Test.MyClass)
    IL_000d: stloc.0
    IL_000e: ret
} // end of method Main::Main1
4

4 に答える 4

2

新しい参照は作成されません。

しかし、それを返すことにも意味がありません。これで十分です:

 public void SomeMethod(MyClass myClass)
 {
    myClass.name = "John";

 }

上記は自然であり、実際にはあなたが提案する方法よりも複雑ではありません。

于 2012-10-12T19:49:33.337 に答える
1

クラスはメソッドへの参照として渡されるため、返すのと同じものを変更します。

参照型に基づくオブジェクトがメソッドに渡されると、オブジェクトのコピーは作成されません。代わりに、メソッド引数として使用されているオブジェクトへの参照が作成され、渡されます。したがって、この参照を通じて行われた変更は、呼び出し元のメソッドに反映されます。

ソース: http: //msdn.microsoft.com/en-us/library/ms173114 (v = vs.80).aspx

読みやすさについて:あなたの方法は常に自明でなければなりません。私の意見では、メソッドの名前はそれが何をするかについて何かを言うべきです。

void AddClientContextToContainer(Container destination)
于 2012-10-12T19:49:23.650 に答える
1

あなたの場合、オブジェクトのインスタンスを1つ作成しています。実際のインスタンスは、を介して作成されますnew。参照は基本的に単なる整数です(32ビットシステムでは32ビット、64ビットシステムでは64ビット)。その整数は、メモリ内のオブジェクトインスタンスの場所を参照します。「新しい参照の作成」は、基本的に新しい整数の作成と同じ量の作業です(つまり、ごくわずかです。これは、コンピューターで実行できる最小の作業単位です)。

別の方法とは対照的に、コードvoidは参照の2つの(冗長な)コピーを実行します。(一度メソッドパラメーターをスタックの戻り値にコピーし、次にその戻り値から元の変数に戻します。)

そこにある実際の追加作業量はごくわずかです。それは存在しますが、それは本当に非常に小さいです。ここでの懸念は、単に読みやすさの1つである必要があります。そのコードが読みやすく、理解しやすいと感じた場合は、問題ありません。これは通常、が不変の場合にのみ使用されるパターンでMyClassあり、戻り値は渡されたインスタンスではなく新しいインスタンスへの参照であることに注意してください。これにより、コードを読んでいる他の人が混乱する可能性があります。オブジェクトが不変であると誤って想定した場合、それは...悪いことにつながる可能性があります。

メソッドがvoidを返すようにすることを提案する人もいますが、クラスが不変になるのは理にかなっていると思います。あなたはすでにより不変のパターンに従っています。

于 2012-10-12T20:03:35.317 に答える
1

あなたの質問に答えるために、はい、コンパイラは戻り値を同じオブジェクトに再割り当てしないほど賢いです。ReflectorまたはdotPeekを使用してコードを開くと、コードは次のようになります。

public void Main()
{
    MyClass myClass = new MyClass();
    //return value back to itself
    myClass = SomeMethod(myClass);
}

単にに変換されます:

public void Main()
{
    this.SomeMethod(new MyClass());
}

reassign変数を使用して何かを行ったとしても、コンパイラーによって削除されます。たとえば、コンパイラはこれを変換します:

public void Main()
{
    MyClass myClass = new MyClass();
    //return value back to itself
    myClass = SomeMethod(myClass);

    Console.WriteLine(myClass.name);
}

それに:

public void Main()
{
    Console.WriteLine(this.SomeMethod(new MyClass()).name);
}

しかし、LewsTherinとRobertJeppesenが言ったように、それは悪い習慣であり、誤解を招く可能性があるため、そうすべきではありません。

于 2012-10-12T20:16:17.237 に答える