【问题标题】:Passing interface members by value按值传递接口成员
【发布时间】:2013-01-09 09:34:58
【问题描述】:
    public void MethodSample1(Itest variable)
    {
        variable.TestString = "some sample data";
        Itest var1 = variable;
        Console.WriteLine(variable.TestString);
        MethodSample2(variable);
        Console.WriteLine(variable.TestString);
        Console.WriteLine(var1.TestString);

    }

    public void MethodSample2(Itest variable)
    {
        variable.TestString = "testdata";
    }

    public interface Itest
    {
      string TestString { get; set; }
    }

预期两个控制台输出行都打印“一些示例数据”,但似乎TestString 正在被新值覆盖?是不是像“默认情况下在 C# 中所有值都是按值传递的?”。

简而言之,如何保存MethodSample1中“TestString”的值?

(我遇到了这个问题,因为我所有的项目都基于一个界面)

即使保留了价值,它也会反映!奇怪!

【问题讨论】:

  • 这不是我几分钟前刚读到的同一个问题吗?

标签: c# .net visual-studio-2010 .net-4.0


【解决方案1】:

对于您当前的问题,我认为您不能阻止任何方法修改传递给它的参数。

您的variable 是一个引用类型对象,在C# 中,引用类型的地址是按值传递给方法的,这就是您看到变化的原因。例如,如果你的方法写成这样:

public void MethodSample2(Itest variable)
{
    variable = null;
}

您在MethodSample1 方法中不会看到更改,因为引用地址是按值传递的。

这不像“在 C# 中默认所有值都通过 价值?”。

值类型是按值传递的,在您的情况下,variable 是一个引用类型。

你应该看到Parameter Passing C# by Jon Skeet

不确定为什么必须修改传递的对象,对于解决方法,您可以创建属性的临时副本,然后在方法存在之前设置该值。

【讨论】:

  • 感谢 Habib “你的变量是一个引用类型的对象”。但是,我试图保留我的变量。即使那样也无济于事!请查看我更新的问题。
  • @nowhewhomustnotbenamed.,按照您保存它的方式,它再次复制了对新变量 var1 的引用。您需要克隆它,或者简单地说,创建一个全新的变量副本。你目前有浅拷贝。你需要深拷贝,见:stackoverflow.com/questions/184710/…
  • @nowhewhomustnotbenamed.,你可能会看到:stackoverflow.com/questions/129389/…
【解决方案2】:

参数确实是按值传递的,但你传递的值是对原始对象的引用

如果要保留原始对象的属性,则需要传递原始对象的副本。您可以将 Clone() 方法添加到接口或类似的东西:

public interface ITest
{
    string TestString { get; set; }
    ITest Clone();      
}

public class Test : ITest 
{
    string TestString { get; set; }
    ITest Clone() { 
        return new Test() { 
            TestString = this.TestString 
        }; 
    }
}

或者,您可以重新考虑当前的方法。你真的需要改变接口的属性吗?或者你可以使用字符串类型的变量吗?

【讨论】:

  • 是的,这正是我想要的......但我究竟如何“你需要传递原始对象的副本”。 ?
  • @nowhewhomustnotbenamed。如何复制对象是另一回事。您可以将 ICloneable 添加到您的接口(或向其添加一个 Clone() 方法),这将要求您的接口的实现者能够克隆自己。或者,您可以重新考虑当前的方法。你真的需要改变接口的属性吗?或者你可以使用字符串类型的变量吗?
  • 谢谢 Botz.. 但是,我有一个在我的项目中接受此接口的方法(抱歉无法发布真实示例,它非常庞大!).. 所以,我需要调用该方法(两次使用不同的输入)与接口成员,但保留原始成员。你能给我一些 IClone 的代码示例吗?感谢您让我知道!
  • @nowhewhomustnotbenamed。这很简单,只需创建一个新实例并复制所有属性即可。请参阅我的答案中的编辑。
【解决方案3】:

MethodSample1中“TestString”的值如何保存?

将其存储在局部变量中。

public void MethodSample1(Itest variable)
{
    variable.TestString = "some sample data";
    string localTestString = variable.TestString;

    Console.WriteLine(variable.TestString);

    MethodSample2(variable);
    variable.TestString = localTestString;

    Console.WriteLine(variable.TestString);

}

但是,这是错误的做事方式。如果您多说一些您想要实现的目标,我们可以提供更多帮助。

【讨论】:

    猜你喜欢
    • 2015-01-21
    • 1970-01-01
    • 2020-12-19
    • 2015-02-16
    • 1970-01-01
    • 2019-10-07
    • 2012-11-03
    • 2016-07-02
    • 1970-01-01
    相关资源
    最近更新 更多