【问题标题】:which is better in this case, return or ref在这种情况下哪个更好,返回或参考
【发布时间】:2013-04-17 01:03:05
【问题描述】:

假设我有以下一组静态函数

这里我通过引用发送变量:

public static void ProcessEmailMessage(ref string HTML)
        {
            ModifyLinks(ref HTML);
            AddFakeImage(ref HTML);
        }

        public static void ModifyLinks(ref string HTML)
        {
            //modify HTML links 
        }


        public static void AddFakeImage(ref string HTML)
        {
            //adds an image to the HTML
        }

这里我按值发送变量

public static string ProcessEmailMessage(string HTML)
        {
            HTML = ModifyLinks(HTML);
            HTML = AddFakeImage(HTML);
            return HTML;
        }

        public static string ModifyLinks(string HTML)
        {
            //modify HTML links
            return HTML;
        }


        public static string AddFakeImage(string HTML)
        {
            //adds an image to the HTML
            return HTML;
        }

哪一个更有意义,两者之间有性能差异吗?

【问题讨论】:

    标签: c# return ref


    【解决方案1】:

    尽可能避免使用 out- 和 ref 参数。

    带 ref 和 out 参数的方法比较难用,需要声明一个变量来保存结果,语义比较难理解。性能差异(如果有的话)可以忽略不计。

    在这种情况下,Visual Studio 中的代码分析可能会针对它们的使用发出警告。

    有关更详细的说明,请参阅http://msdn.microsoft.com/en-us/library/ms182131

    【讨论】:

    • 外部文档的链接很好,但您应该在此处包含摘要。如果外部链接中断,那么答案应该仍然有用。
    • @cdhowie:感谢您指出这一点。我已经编辑了这篇文章以包含更多的摘要。
    【解决方案2】:

    我更喜欢像 builder 这样的东西:

    新的 EmailMessageProcessor(html).WithModifiedLinks().WithFakeImages()。

    所以没有 ref 参数,一切都被封装了。

    【讨论】:

      【解决方案3】:

      如果您需要返回多个对象,请使用ref/out,如果您可以使用return 简单地返回一个对象,请使用return
      ref 会使您的代码不必要地晦涩难懂,并且在这种情况下会产生不必要的写入开销。
      您应该始终尽量保持您的代码简单易懂。

      【讨论】:

        【解决方案4】:

        差别不大,但我会选择“返回”。如果可能,尽量避免使用“ref”。

        原因是你不必在传递另一个调用的结果之前声明一个变量,你可以链接调用:

        带参考:

        string modifyMe = GetMeString();
        ModifyLints(ref modifyMe);
        AddFakeImage(ref modifyMe);
        

        比较返回:

        string result = AddFakeImage(ModifyLinks(GetMeString()));
        

        【讨论】:

          【解决方案5】:

          两者之间的性能差异可以忽略不计。这几乎完全是语法偏好问题。

          标准约定将涉及返回一个新字符串,而不是修改通过引用传递的参数。在某些情况下它更容易使用(即当您没有命名变量时;例如,当您想要传入方法或属性的返回值而不是字段时)。

          【讨论】:

            【解决方案6】:

            使用ref 可能会对性能造成更多影响,因为这相当于在分配给变量时增加了一层间接性。但是,这种差异可能可以忽略不计。

            我更喜欢返回字符串的表单,因为这更能说明实际发生的情况,并且如果您愿意,可以将方法调用链接在一起:

            return AddFakeImage(ModifyLinks(HTML));
            

            使用ref 表单,您强制 调用代码来声明变量,否则它们可能不需要这样做。这妨碍了可读性并增加了无意义的样板代码的发生率。

            【讨论】:

            • 从技术上讲,在这两种情况下都声明了一个变量,这只是程序员是否需要知道它的问题。在您提供的代码示例中,存在一个隐式未命名的局部变量。现在,话虽如此,不必知道它很好,但从性能的角度来看,它并没有什么不同。
            • @Servy JIT 编译时会有一个寄存器,但我展示的代码示例将声明比原始代码少一个本地。缩写的 IL 将是 ldarg.0; call; call; ret;。所以不,没有“附加变量”,至少在翻译成本机代码之前是这样。 (而且原生代码中实际上并不存在变量,只是寄存器和内存位置。变量的概念比原生代码更高级。)
            • 在这两种情况下,无论是否存在命名本地,当您到达实际的处理器指令级别时,两者都很可能已注册,但两者都可能存储在某个位置如果不可能的话,在内存中。
            • @Servy 当然。但在那个层面上,我们不再谈论变量。如果您的观点是两者都将具有相同的执行速度并且可能具有完全相同的本机表示,那是正确的。但是,我的示例与性能关系不大,而与编码风格的更多选项有关。我从来没有暗示我的示例比原始示例更快,如果我建议这种级别的微优化将是邪恶的。
            猜你喜欢
            • 1970-01-01
            • 2016-12-24
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多