首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在C#中仅输入参数

在C#中仅输入参数
EN

Stack Overflow用户
提问于 2013-10-18 03:02:57
回答 3查看 357关注 0票数 0

最近有人问我,在一个方法中是否可以有一个仅限输入的参数?我对这个问题的直接回答是“不”,但当我再次思考时,我不确定我是否分享了正确的信息。另外,我没有一个合理的解释来解释为什么.NET不允许我们有一个仅输入的参数,就像我们在实现Contravariance时使用的那样。

EN

回答 3

Stack Overflow用户

发布于 2013-10-18 03:13:13

你可以在这里读到关于Passing Parameters的内容。

我认为当你说“仅限输入”时,你指的是通过值传递的参数。

在c#中,通常按值传递参数。当你传递一个对象时,你是在通过值传递一个“指针”。所以如果你改变了指针所指向的位置,外部的变量也不会改变。但是如果你改变了对象的东西,因为两个“指针”都指向同一个对象,所以它们都会看到变化。

因此,您可以通过"value“传递所有内容,但如果您正在传递对象,则必须创建它的副本,以避免它被您正在调用的方法修改。

你可以在这里看到一个小的测试例子来理解我的意思。

代码语言:javascript
复制
[TestMethod]
    public void TestMethod()
    {
        var john = new Person() { Name = "John" };
        var tom = new Person() { Name = "Tom" };

        var person1 = john;
        var person2 = tom;

        SwapPersonsMethod1(person1, person2);
        //Person1 is still John
        Assert.AreEqual(person1, john);
        //Person2 is still Tom
        Assert.AreEqual(person2, tom);

        SwapPersonsMethod2(ref person1, ref person2);
        //Person1 is still Tom
        Assert.AreEqual(person1, tom);
        //Person2 is still John
        Assert.AreEqual(person2, john);

        UpdateName(person1, "Tomas");
        //Person1 is pointing to var tom, and its name now is Tomas.
        Assert.AreEqual(person1.Name, "Tomas");
        Assert.AreEqual(tom.Name, "Tomas");

        SwapPersonsMethod3(person1, person2, "Jonathan");
        //Person1 is still Tom
        Assert.AreEqual(person1, tom);
        //Person2 is still John
        Assert.AreEqual(person2, john);

        //John name has changed to Jonathan
        Assert.AreEqual(person2.Name, "Jonathan");
        Assert.AreEqual(john.Name, "Jonathan");
    }

    private void UpdateName(Person person, string name)
    {
        person.Name = name;
    }

    private void SwapPersonsMethod1(Person person1, Person person2)
    {
        var aux = person1;
        person1 = person2;
        person2 = aux;
    }

    private void SwapPersonsMethod2(ref Person person1, ref Person person2)
    {
        var aux = person1;
        person1 = person2;
        person2 = aux;
    }

    private void SwapPersonsMethod3(Person person1, Person person2, string name)
    {
        var aux = person1;
        person1 = person2;
        person2 = aux;
        UpdateName(person1, name);
    }

    public class Person
    {
        public string Name { get; set; }
    }
票数 3
EN

Stack Overflow用户

发布于 2013-10-18 03:45:29

我在这里进行了一次大胆的尝试,但听起来您似乎是在问是否可以防止被调用函数更改参数的内容(如调用者所见)。

代码语言:javascript
复制
public void Run()
{
    Person Bob = New Person();
    Bob.LikesToProgram = false;
    Helper(Bob);
    Console.WriteLine("Bob likes to program = " + Bob.LikesToProgram);
    //Output: Turns out Bob likes to program!!!
}

public void Helper(Person input)
{
    input.LikesToProgram = true;
}  

你的问题的答案是。。。这取决于参数类型!

您始终可以通过模式创建不可变类型!

通过值传递的

所有参数都是“按值”的。有趣的是,如果参数不是一个值,而是指向该值(尽管引用会更准确)。

这就把我们带到。。。

对象

我们在那里做的是Passing a reference to an

(正如@Servy所指出的,“通过值传递引用”。)

如果我们传递了一个原语(不是引用类型),Helper中的更改将停留在helper中。。。

原语

要使原语的行为类似于引用类型(这将与您所要求的完全相反),您需要使用ref keyword

"Object“异常

某些语言允许您通过显式定义 immutable对象。也就是说,有直接的编译器支持来实现不可变性。请参阅链接的文章以获取示例。

换句话说,如果我创建了一个Person并将实例传递给一个新方法,那么该方法就会生效。接收自己的person副本!

string继承自Object,但当您更改String时,会创建一个新的string实例。

需要明确的是,通过模式还有其他不可变的对象,但直接支持意味着您永远不需要编写

代码语言:javascript
复制
public void Run()
{
    String foo = "foo";
    Helper(foo);
}

public void Helper(String input)
{
    input = new String(Foo + "Bar");
    //Or CopyTo as seen in Arrays, etc.
}

总会有办法的!

  1. 使所有属性都是只读的,并且只允许在实例化时设置值(通过构造函数)。想要更改一个值吗?您需要创建一个新实例!

如果您使用此策略,则如果对象实现iCloneable将非常有用。为什么要问iCloneable?Deep Copy Vs Shallow

  1. 假设你正在编写一个外部库,并且希望你的库的使用者看到你的对象是不可变的……另一方面,您不能!)例如:Internal

希望这能有所帮助!

更新: @Dzyann首先提供了一个类似的答案(我太冗长了,活该)。如果你喜欢我的回答,也一定要给他打个勾。

票数 0
EN

Stack Overflow用户

发布于 2013-10-18 03:17:14

我认为,您应该停止在c#中使用不同的名称。您可以在MSDN上阅读有关refout关键字的内容。我只想让你知道原始类型

代码语言:javascript
复制
void MyVoid(int p1)

通过值传递-表示它们被复制。在这里我必须纠正一下:其他类型也传递了byVal,但是作为对现有对象的引用。

如果通过引用传递所有参数,您的代码将更快,但更危险,因为这样可以节省时间,因为不复制它。但是,在这种情况下,您将需要具有较高的编码规则。

“我没有一个合理的解释来解释为什么.NET不允许我们有一个只有输入的参数”--这正是.Net对传递给byval的原始类型有效的解释。

想象一下,如果.net不得不复制所有作为参数传递的对象结构,它的效率会有多低?我猜,这就是为什么MS决定将对象类型作为引用传递

票数 -1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/19435032

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档