4

out再帰メソッドでパラメーターを使用できますか? 可能であれば、次のコードでどのように行うことができますか?

private void PrepareDir(out List<_File> listFiles,string root,string dirPath) {
    DirectoryInfo dirRoot = new DirectoryInfo(dirPath);
    FileInfo [] Files = dirRoot.GetFiles();
    dirPath = dirPath.Substring(root.Length);

    foreach (FileInfo file in Files) {
        _File _file = new _File();
        _file.Name = dirPath + "\\" + file.Name;
        _file.Path = file.FullName;
        _file.Size = file.Length;
        listFiles.Add(_file);
    }

    foreach (DirectoryInfo dir in dirRoot.GetDirectories()) {
        PrepareDir(out listFiles, root, dir.FullName);
    }
}

private void btnButton1_Click(object sender, EventArgs e) {
    List<_File> Files = new List<_File>();
    PrepareDir(out Files,currAddress, currAddress);
}
4

2 に答える 2

5

ここで使用する必要がない理由について、より直接的に回答を書き直すことにしoutました。あなたの質問の根本は、値渡し、参照渡し、および参照渡しされる参照型の間の一般的な混乱の違いを理解していないことにあると思うので、私はこれをかなり長く書きましたまた、これは再帰のみを明示しているわけではないことに注意してください。

C# では、参照型は既定で値渡しされます。多くの人が参照型を参照渡しと混同することがありますが、重要な違いがあります。わかりやすくするために、参照型をそのまま参照し、reforoutキーワードを使用して参照渡しします。

参照型を値で渡すと、メモリ内の格納場所への参照であるため、変更を加えて永続化できます。この例を見てください。

public class MyRefType
{
    public int Value { get; set; }
}

public void Foo() {
    MyRefType type = new MyRefType();
    AddOne(type);
}

public void AddOne(MyRefType type) {
    type.Value++;
}

ここで何が起こるかというと、クラスtypeの値が 1 になるということです。これが参照型の性質です。の場合、オブジェクトへの参照を保持する代わりにコピーtypestruct作成されるため、Foo メソッド内の値は 0 のままです。

参照型を値で渡すことの意味を理解していただければ幸いです。実際に、参照型を参照で渡すことについて話しましょう。これは、outandrefキーワードを使用して行います。outCLR では、技術的には存在せず、存在するだけであることにすぐに注意してくださいrefout実際にはref、特別な属性が適用されたものとしてメタデータで表され、それらは同じように扱われるべきです。

AddOneここで、追加を行う前に、メソッドで参照型を再割り当てしたいとしましょう。

public class MyRefType
{
    public int Value { get; set; }
}

public void Foo() {
    MyRefType type = new MyRefType();
    AddOne(type);
}

public void AddOne(MyRefType type) {
    type = new MyReferenceType();
    type.Value++;
}

まだ参照型を値で渡しているためtype、メソッド内のの値はFoo0 のままです。元の格納場所を再割り当てする代わりに、メモリ内の別の格納場所を初期化しただけです)。しかし、実際には参照型を参照渡ししたいので、実際に行う必要があります。

public class MyRefType
{
    public int Value { get; set; }
}

public void Foo() {
    MyRefType type = new MyRefType();
    AddOne(ref type);
}

public void AddOne(ref MyRefType type) {
    type = new MyReferenceType();
    type.Value++;
}

typeこれで、メソッド内のの値はFoo1 になります。これは、メモリ内に新しい場所を作成する代わりに、参照が指している同じ保存場所を再利用したためです。

では、これはどのように適用されoutますか? これは、使用法が異なる場合outと同じであることを忘れないでください。ref違いは、refでは参照を初期化せずにメソッドを終了できるのに対し、outではメソッドが戻る前に明示的に初期化する必要があることです。

したがって、outここで使用する場合、既存の参照シマンティクスが既に機能しているため、まったく必要ありません。これが少し解消されることを願っています。

于 2012-04-25T03:23:49.367 に答える
2

outコード例でキーワードを誤用しています。あなたList<_File>は参照型として渡され、そのリストに加えられた変更は呼び出し元のリストに影響します。out呼び出し元の識別子を再割り当てする場合にのみ、パラメーターを渡す必要があります。

検討:

public bool Foo()
{
  List<int> list = new List<int>();
  list.Add(1);
  Bar(out list);
  return list.Contains(1);
}

public void Bar(out List<int> list)
{
  list = new List<int>();
  list.Add(2);
}

Foofalseを返します。

一方、次のBarような場合:

public void Bar(List<int> list)
{
  list = new List<int>();
  list.Add(2);
}

その後Foo、trueを返します。詳細については、を参照outしてください。

を使用しなくても、コードはそのまま機能しますout。そして、実際にはコンパイルされません-そしてそれをコンパイルさせると、あなたがやろうとしていることに不必要な複雑さが増します。あなたの場合には使用しないoutでください。

于 2012-04-25T03:13:04.080 に答える