使用ref关键字的替代方法?

时间:2016-09-11 20:43:29

标签: c#

作为一名新手,我已经了解了使用ref关键字传递参数的危险。我想当一个程序的一部分修改一个ref变量然后改变其他地方发生的事情时,很有可能弄乱代码。物体最终会紧密耦合。 (我承认there may be places where ref is worthwhile。)我还不知道,而且我在询问的是替代方案。

例如,在一个程序中,我在启动时创建一个通用列表,我在程序的方法中操作。在一种方法中:

//a user is asked a question  
//if the response is yes, the list is modified one way and the method returns true  
//if the response is no, the list is modified a different way and the method returns false. 

因此该方法返回一个布尔值,我将列表作为ref传递。我有几个类似的方法,每个方法都询问用户独特的问题,然后以某种方式修改列表。

似乎就像典型的替代方案可能是将列表和布尔字段捆绑到自己的类中。不知何故,这似乎只是为了方便而创建一个对象,只是为了保存两个数据,而不与任何现实世界的实体建立连接。

那么,你如何(伪)编码一个返回泛型列表和布尔值的方法?

编辑:这是一些实际的代码

 private static bool AskExptQuestion(ref List<StatTest> testList)
        {
            Console.Write(Constants.ExptQText); //experimental groups?
            string response = Console.ReadLine();

            //if response==y, it's experimental 
            if (response == "y")
            {
                //so select all experimental
                var q1List =
                from test in testList
                where test.isExperimental == true
                select test;

                //to copy resulting IEnumerable<List> (q1list) to generic List, must copy/cast IEnumerable to a List<t>
                testList = q1List.ToList();
                return true;
            }
            //and if response==n, it's not experimental 
            else
            {
                //so select all non-experimental
                var q1List =
                from test in testList
                where test.isExperimental == false
                select test;

                testList = q1List.ToList();
                return false;
            }

        }

3 个答案:

答案 0 :(得分:1)

返回一个列表(或几乎任何其他东西,除此之外)及其特征,例如布尔值,是一个&#34;海报孩子&#34; ref / out功能。此模式在标准.NET库中的几个位置使用:

  • Dictionary.TryGetValue使用此模式,根据字典中键的存在,返回truefalse,并将out设置为返回对象
  • Integer.TryParse(以及其他数字类型)使用此模式,在解析成功时返回true,并在out参数中设置值

refout之间的区别在于ref为您的方法提供了保留旧对象/值或提供新对象/值的选项,而out在方法返回之前强制您提供新的。

创建一个新类只是为了将两个不相关的类型捆绑在一起是没有意义的。

此外,重要的是要了解即使在refout未传递参数的情况下,也可能会发生对方法参数的修改。当您传递一个可变的引用对象(即class)类型时,在方法内部对对象所做的任何修改都会在调用者中可见。

传递refout时唯一的区别是,您可以使用新的替换对象本身,同时传递不带{{的引用类型1}}仅限于改变传入的对象本身。

答案 1 :(得分:1)

通过阅读您的示例和评论,您可能只想要将某些过滤器应用于集合。为什么不让函数返回过滤器?

private static Predicate<StatTest> AskExptQuestion()
{
    Console.Write(Constants.ExptQText);  // experimental groups?
    bool response = Console.ReadLine() == "y";  // maybe wrap this up in a function to read a yes/no answer
    return t => t.isExperimental == response;
}

但是,您可能仍需要bool返回值,这可能会成为out参数。目前尚不清楚这是什么。

答案 2 :(得分:-2)

c#参数中的

按值传递。 对象类型(类)由指向内存中实例的指针所强调。 在将对象传递给方法的地方,指针被复制到参数,然后指向同一个实例。

如果我有:

void foo(MyClass param)
{
    param.x = 7;
}

以及我做的其他地方:

MyClass obj = new MyClass();
obj.x = 5;
foo(obj);

然后在调用foo()后,obj的x属性为7。

如果foo是:

void foo(MyClass param)
{
    param = new MyClass();
    param = 7;
}

然后我的原始obj仍然会有x等于5.这是因为我跑过了param正在查看的实例。

现在&#34; ref&#34;关键字:

void foo(ref MyClass param)
{
    param = new MyClass();
    param = 7;
}

如果我这样打电话:

MyClass obj = new MyClass();
obj.x = 5;
foo(ref obj);

在这个组合中,我的obj将设置为MyClass的新实例,并且x等于7. ref表示方法中的变量与传递的变量相同,而不仅仅指向同一个实例从...开始。