从方法返回两个值的最佳方式是什么?

发布于 2024-08-31 18:32:54 字数 4679 浏览 5 评论 0原文

当我必须编写返回两个值的方法时,我通常会按照以下返回 List 的代码进行操作。或者,如果我必须返回id和字符串,那么我返回一个List,然后用index数字和重塑价值观。

这种通过索引进行重铸和引用似乎不太优雅,所以我想为返回两个值的方法养成一个新习惯。最好的模式是什么?

using System;
using System.Collections.Generic;
using System.Linq;

namespace MultipleReturns
{
    class Program
    {
        static void Main(string[] args)
        {
            string extension = "txt";

            {
                List<string> entries = GetIdCodeAndFileName("first.txt", extension);
                Console.WriteLine("{0}, {1}", entries[0], entries[1]);
            }

            {
                List<string> entries = GetIdCodeAndFileName("first", extension);
                Console.WriteLine("{0}, {1}", entries[0], entries[1]);
            }

            Console.ReadLine();
        }

        /// <summary>
        /// gets "first.txt", "txt" and returns "first", "first.txt"
        /// gets "first", "txt" and returns "first", "first.txt"
        /// it is assumed that extensions will always match
        /// </summary>
        /// <param name="line"></param>
        public static List<string> GetIdCodeAndFileName(string line, string extension)
        {
            if (line.Contains("."))
            {
                List<string> parts = line.BreakIntoParts(".");
                List<string> returnItems = new List<string>();
                returnItems.Add(parts[0]);
                returnItems.Add(line);
                return returnItems;
            }
            else
            {
                List<string> returnItems = new List<string>();
                returnItems.Add(line);
                returnItems.Add(line + "." + extension);
                return returnItems;
            }
        }

    }

    public static class StringHelpers
    {
        public static List<string> BreakIntoParts(this string line, string separator)
        {
            if (String.IsNullOrEmpty(line))
                return null;
            else
            {
                return line.Split(new string[] { separator }, StringSplitOptions.None).Select(p => p.Trim()).ToList();
            }
        }
    }
}

添加:

好的,谢谢大家,我最喜欢“返回自定义类”答案,从来没有真正想过out 很容易阅读,对我来说似乎是一种黑客攻击,以一种方式返回第一个变量,以另一种方式返回第二个变量,这是我返回自定义类的重构

using System;
using System.Collections.Generic;
using System.Linq;

namespace MultipleReturns
{
    class Program
    {
        static void Main(string[] args)
        {
            string extension = "txt";

            {
                IdCodeFileNamePair pair = GetIdCodeAndFileName("first.txt", extension);
                Console.WriteLine("{0}, {1}", pair.IdCode, pair.FileName);
            }

            {
                IdCodeFileNamePair pair = GetIdCodeAndFileName("first", extension);
                Console.WriteLine("{0}, {1}", pair.IdCode, pair.FileName);
            }

            Console.ReadLine();
        }

        /// <summary>
        /// gets "first.txt", "txt" and returns "first", "first.txt"
        /// gets "first", "txt" and returns "first", "first.txt"
        /// it is assumed that extensions will always match
        /// </summary>
        /// <param name="line"></param>
        public static IdCodeFileNamePair GetIdCodeAndFileName(string line, string extension)
        {
            if (line.Contains("."))
            {
                List<string> parts = line.BreakIntoParts(".");
                List<string> returnItems = new List<string>();
                return new IdCodeFileNamePair { IdCode = parts[0], FileName = line };
            }
            else
            {
                List<string> returnItems = new List<string>();
                return new IdCodeFileNamePair { IdCode = line, FileName = line + "." + extension };
            }
        }

    }

    public static class StringHelpers
    {
        public static List<string> BreakIntoParts(this string line, string separator)
        {
            if (String.IsNullOrEmpty(line))
                return null;
            else
            {
                return line.Split(new string[] { separator }, StringSplitOptions.None).Select(p => p.Trim()).ToList();
            }
        }
    }

    public class IdCodeFileNamePair
    {
        public string IdCode { get; set; }
        public string FileName { get; set; }
    }
}

When I have to write methods which return two values, I usually go about it as in the following code which returns a List<string>. Or if I have to return e.g. a id and string, then I return a List<object> and then pick them out with index number and recast the values.

This recasting and referencing by index seems inelegant so I want to develop a new habit for methods that return two values. What is the best pattern for this?

using System;
using System.Collections.Generic;
using System.Linq;

namespace MultipleReturns
{
    class Program
    {
        static void Main(string[] args)
        {
            string extension = "txt";

            {
                List<string> entries = GetIdCodeAndFileName("first.txt", extension);
                Console.WriteLine("{0}, {1}", entries[0], entries[1]);
            }

            {
                List<string> entries = GetIdCodeAndFileName("first", extension);
                Console.WriteLine("{0}, {1}", entries[0], entries[1]);
            }

            Console.ReadLine();
        }

        /// <summary>
        /// gets "first.txt", "txt" and returns "first", "first.txt"
        /// gets "first", "txt" and returns "first", "first.txt"
        /// it is assumed that extensions will always match
        /// </summary>
        /// <param name="line"></param>
        public static List<string> GetIdCodeAndFileName(string line, string extension)
        {
            if (line.Contains("."))
            {
                List<string> parts = line.BreakIntoParts(".");
                List<string> returnItems = new List<string>();
                returnItems.Add(parts[0]);
                returnItems.Add(line);
                return returnItems;
            }
            else
            {
                List<string> returnItems = new List<string>();
                returnItems.Add(line);
                returnItems.Add(line + "." + extension);
                return returnItems;
            }
        }

    }

    public static class StringHelpers
    {
        public static List<string> BreakIntoParts(this string line, string separator)
        {
            if (String.IsNullOrEmpty(line))
                return null;
            else
            {
                return line.Split(new string[] { separator }, StringSplitOptions.None).Select(p => p.Trim()).ToList();
            }
        }
    }
}

Added:

Ok, thanks everyone, I like the "return a custom class" answers best, never really thought out was that easy to read, seems like a hack to me returning the first variable one way and the second another, here is my refactoring returning a custom class:

using System;
using System.Collections.Generic;
using System.Linq;

namespace MultipleReturns
{
    class Program
    {
        static void Main(string[] args)
        {
            string extension = "txt";

            {
                IdCodeFileNamePair pair = GetIdCodeAndFileName("first.txt", extension);
                Console.WriteLine("{0}, {1}", pair.IdCode, pair.FileName);
            }

            {
                IdCodeFileNamePair pair = GetIdCodeAndFileName("first", extension);
                Console.WriteLine("{0}, {1}", pair.IdCode, pair.FileName);
            }

            Console.ReadLine();
        }

        /// <summary>
        /// gets "first.txt", "txt" and returns "first", "first.txt"
        /// gets "first", "txt" and returns "first", "first.txt"
        /// it is assumed that extensions will always match
        /// </summary>
        /// <param name="line"></param>
        public static IdCodeFileNamePair GetIdCodeAndFileName(string line, string extension)
        {
            if (line.Contains("."))
            {
                List<string> parts = line.BreakIntoParts(".");
                List<string> returnItems = new List<string>();
                return new IdCodeFileNamePair { IdCode = parts[0], FileName = line };
            }
            else
            {
                List<string> returnItems = new List<string>();
                return new IdCodeFileNamePair { IdCode = line, FileName = line + "." + extension };
            }
        }

    }

    public static class StringHelpers
    {
        public static List<string> BreakIntoParts(this string line, string separator)
        {
            if (String.IsNullOrEmpty(line))
                return null;
            else
            {
                return line.Split(new string[] { separator }, StringSplitOptions.None).Select(p => p.Trim()).ToList();
            }
        }
    }

    public class IdCodeFileNamePair
    {
        public string IdCode { get; set; }
        public string FileName { get; set; }
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

窗影残 2024-09-07 18:32:54

我更喜欢创建一个具有两个属性的轻量级类(见下文),或者使用元组(现在可以嵌入到 .NET 4 的框架中,但编写自己的属性并不难)

class MyReturnValue
{
    public string Id { get; set; }
    public string Name { get; set; }
}

I prefer either to create a lightweight class with two properties (see below), or to use a tuple (now available baked into the framework in .NET 4 but not hard to write your own)

class MyReturnValue
{
    public string Id { get; set; }
    public string Name { get; set; }
}
万人眼中万个我 2024-09-07 18:32:54

从 4.0 开始,您可以返回 元组

You could return a tuple, starting with 4.0.

送舟行 2024-09-07 18:32:54

使用关键字 out

http://msdn.microsoft。 com/en-us/library/ee332485.aspx

这比转换对象列表的特定元素方式要好。

Use keyword out

http://msdn.microsoft.com/en-us/library/ee332485.aspx

This is way better than casting specific elements of a list of objects.

因为看清所以看轻 2024-09-07 18:32:54

另一种选择是返回 KeyValuePair

Another option is to return a KeyValuePair<int, string>.

数理化全能战士 2024-09-07 18:32:54

为什么不使用 public static void GetIdCodeAndFileName(string line, string extension, out string id, out string fileName)

Why not public static void GetIdCodeAndFileName(string line, string extension, out string id, out string fileName)?

生活了然无味 2024-09-07 18:32:54

我要么使用参数,要么创建一个带有属性的结构(对于属性初始值设定项语法)并返回它。创建自定义结构/类的优点是变量命名可以与传递的数据相匹配。这使得代码更具可读性。

IdAndString GetIDAndString()
{
    return new IdAndString()
    {
        ID = 1,
        Str = "123"
    };
}

struct IdAndString
{
    public int ID { get; set; }
    public string Str { get; set; } 
}

I either use out params, or create a struct with properties (for the property initializer syntax) and return that. Creating a custom struct/class has the advantage of variable naming that can match the data being passed. This makes the code more readable.

IdAndString GetIDAndString()
{
    return new IdAndString()
    {
        ID = 1,
        Str = "123"
    };
}

struct IdAndString
{
    public int ID { get; set; }
    public string Str { get; set; } 
}
寄意 2024-09-07 18:32:54

我建议使用像马克建议的轻量级物体。但也有其他模式。

另一种简单的方法是使用按引用调用属性。就像,调用者发送一个空数组作为参数,该参数将由函数填充。

I would recommend using of a Light weight object like Mark suggested. But there are other patterns as well.

Another simple approach is, use the call by reference property. Like, the caller sends an empty array as a parameter, which will be populated by the function.

尾戒 2024-09-07 18:32:54

模板 Pair 怎么样?当然,如果要传递相同的数据类型,您可以为此构造自定义数据类型,但它不是通用的。

(或者 C# 是否允许您即时生成类?更新:可以忽略这一点

How about a template Pair<T,V>? Of course you can construct custom data-types for this if the same ones will be passed around, but it's not as generic.

(Or perhaps does C# let you generate classes on-the-fly? update: ok ignore this bit)

虚拟世界 2024-09-07 18:32:54

在 C# 中,没有一种返回两个值的优雅方法。虽然我绝对认为使用 out 参数比返回 List 更好,但这不太可维护或可读。 C# 开发人员期望 out,它由语言直接支持,并且很好地理解它在做什么。

从 4.0 开始,您可以使用 Tuple 代替。

There just plain isn't an elegant way to return two values in C#. Although I definitely think using out parameters is better than returning a List, that's not very maintainable or readable. C# developers expect out, it's supported directly by the language, and it's well understood what it's doing.

Starting in 4.0, you can use a Tuple instead.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文