C#中带"out参数"的递归

Mur*_*sli 4 c# recursion

我可以使用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);
}
Run Code Online (Sandbox Code Playgroud)

Dav*_*son 5

我决定改写我的答案,更直接地说明为什么out在这里没有必要使用.我写这是相当长的,因为我觉得你的问题的根源更多的是不理解按值传递的差异,通过引用传递,和之间的共同困惑引用类型按引用传递.另请注意,这不仅仅是递归.

在C#中,默认情况下,引用类型按值传递.很多人可以将参考类型与通过引用传递混淆,但是有一个重要的区别.为了使自己更清楚,我将按原样引用引用类型,并使用refout关键字通过引用传递.

按值传递引用类型,因为它是对内存中某些存储位置的引用,允许您创建和保留更改.举个例子.

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

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

public void AddOne(MyRefType type) {
    type.Value++;
}
Run Code Online (Sandbox Code Playgroud)

这里会发生的是,该类type现在的值为1.这是引用类型的本质.如果type是a struct,它在Foo方法中的值仍然为0,因为创建了一个副本而不是保持对该对象的引用.

现在,我希望你明白按值传递引用类型的symantics,我们实际上谈传递引用类型引用.这是使用outref关键字完成的.请立即注意,在CLR中,out技术上不存在,只有ref.out实际上在元数据中表示为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++;
}
Run Code Online (Sandbox Code Playgroud)

因为我们仍然按值传递我们的引用类型type,所以方法中的值Foo仍然是0.我们所做的只是初始化内存中的另一个存储位置,而不是重新分配原始存储位置).但是,我们要真正通过我们引用类型的引用,所以我们应该真正做到:

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++;
}
Run Code Online (Sandbox Code Playgroud)

现在的价值typeFoo方法将是1.这是因为我们重复使用的,而不是在内存中创建一个新的位置,参考指向同一个存储位置.

那么这一切是如何适用的out呢?请记住,out这与ref使用不同的语义相同.不同之处在于,ref您可以保留方法而不初始化引用,而使用时out,必须在方法返回之前显式初始化它.

因此,在您使用out此处的情况下,完全没有必要,因为您已经有适用于您的现有引用语义.我希望这有点清楚.