【问题标题】:Is there a way I can return more than one integer from a method? [duplicate]有没有一种方法可以从方法中返回多个整数? [复制]
【发布时间】:2019-08-29 08:52:31
【问题描述】:

我有这样的方法:

private double GetHeight()
{
    return 2;
}

但我希望能够返回两个不同的数字,例如 2 和 3。有什么方法可以在 C# 中做到这一点?

【问题讨论】:

  • 如果需要更多值,则返回数组
  • This 可能正是您所需要的
  • 为了清楚起见:您的方法是否总是返回相同数量的返回值(每个都有特定的语义) - 或者返回值的数量动态 i>,即有时它会是 1(甚至可能是零),而其他时候可能是 20?这很重要。对于固定数字场景:任何元组式答案都是好的;对于动态场景:数组/列表方法很好。
  • 这个问题怎么会有这么多赞?这个问题缺乏大量的努力,在互联网上进行简单的搜索就可以提供答案stackoverflow.com/help/how-to-ask

标签: c#


【解决方案1】:

ValueTuple / 命名元组(在 C# 7.0 中可用)。优点是最简洁,不可变,易于构建。

ValueTuple 结构具有名为 Item1、Item2、Item3 等的字段, 类似于现有 Tuple 类型中定义的属性。

然而,当你初始化一个元组时,你可以使用新的语言 为每个字段提供更好名称的功能。这样做会创建一个 命名元组。命名元组仍然有名为 Item1、Item2 的元素, 第 3 项等等。但它们也有任何这些元素的同义词 你所命名的。通过指定名称来创建命名元组 每个元素。

private (double first, double second) GetHeight()
{
   return (1,2);
}

...

var result = ViaNamedValueTuple();
Console.WriteLine($"{result.first}, {result.second}");

var (first, second) = ViaNamedValueTuple();
Console.WriteLine($"{first}, {second}");

经典元组

C# tuple type

.NET Framework 已经有通用的 Tuple 类。这些课, 但是,有两个主要限制。其一,元组类命名为 它们的属性 Item1、Item2 等等。这些名字没有 语义信息。使用这些元组类型不会启用 传达每个属性的含义。新语言 功能使您能够声明和使用具有语义意义的名称 对于元组中的元素。

public Tuple<int, int> ViaClassicTuple()
{
   return new Tuple<int, int>(1,2);
}

...

var tuple = ViaClassicTuple();
Console.WriteLine($"{tuple.Item1}, {tuple.Item2}");

经典结构

struct (C# Reference)

结构类型是一种值类型,通常用于封装 相关变量的小组,例如坐标 矩形或库存中物品的特征。

public struct ClassicStruct
{
   public int First { get; set; }
   public int Second { get; set; }
   public ClassicStruct(int first, int second)
   {
      First = first;
      Second = second;
   }
}

...

public ClassicStruct ViaClassicStruct()
{
   return new ClassicStruct(1, 2);
}

... 

var classicStruct = ViaClassicStruct();
Console.WriteLine($"{classicStruct.First}, {classicStruct.Second}");

只读结构

readonly (C# Reference)

结构定义上的只读修饰符声明该结构 是不可变的。必须标记结构的每个实例字段 只读,如下例所示:

public readonly struct ReadonlyStruct
{
   public int First { get; }
   public int Second { get; }
   public ReadonlyStruct(int first, int second)
   {
      First = first;
      Second = second;
   }
}

...

public ReadonlyStruct ViaReadonlyStruct()
{
   return new ReadonlyStruct(1, 2);
}

...


var readonlyStruct = ViaReadonlyStruct();
Console.WriteLine($"{readonlyStruct.First}, {readonlyStruct.Second}");

简单类

Classes (C# Programming Guide)

定义为类的类型是引用类型。在运行时, 当您声明引用类型的变量时,该变量包含 值 null 直到您通过以下方式显式创建类的实例 使用 new 运算符,或为其分配兼容类型的对象 可能是在别处创建的

public class SomeClass
{
   public int First { get; set; }
   public int Second { get; set; }
   public SomeClass(int first, int second)
   {
      First = first;
      Second = second;
   }
}

...

public SomeClass ViaSomeClass()
{
   return new SomeClass(1, 2);
}

...


var someClass = ViaSomeClass();
Console.WriteLine($"{someClass.First}, {someClass.Second}");

输出参数

out parameter modifier (C# Reference)

out 关键字导致参数通过引用传递。它使 形式参数 参数的别名,它必须是 多变的。换句话说,对参数的任何操作都是在 论点。类似于 ref 关键字,只是 ref 需要 变量在传递之前被初始化。它也像 in 关键字,除了 in 不允许被调用的方法 修改参数值。要使用 out 参数,两种方法 定义和调用方法必须显式使用 out 关键字。

public bool ViaOutParams(out int first, out int second)
{
   first = 1;
   second = 2;
   return someCondition;
}

...

if(ViaOutParams(out var firstInt, out var secondInt))
   Console.WriteLine($"{firstInt}, {secondInt}");

输出值元组

public bool ViaOutTuple(out (int first,int second) output)
{
   output = (1, 2);
   return someCondition;
}

...

if (ViaOutTuple(out var output))
   Console.WriteLine($"{output.first}, {output.second}");

【讨论】:

  • 注意:在 C# 7.0 + 中可用。
  • 如果目的是保持价值传递,也许结构比类更合适。
【解决方案2】:

制作一个int数组。或者另一种方法是创建类。

【讨论】:

  • 一个数组在这里绝对是一个不好的方法 - 这是相当分配并且每个值的语义含义不清楚;创建一个 class 也会相对分配,但是... readonly struct 就可以了
  • 它还不错,但在当前问题中不需要。
  • 我宁愿有一类强类型的值,而不是猜测数组中有多少以及它们的值代表什么
  • 你也可以列个清单。
  • @VukUskokovic 认为 (list) 有数组的所有问题,加上一个额外的对象和抽象层;把它变成一个列表只会加剧问题,除非我们在语义上返回一个列表
【解决方案3】:

多种方式:

  1. out参数:

    private double GetHeight(out int anotherValue)
    {
        anotherValue = 42;
        return 2;
    }
    
  2. 值元组:

    private (double height, int anotherValue) GetHeight()
    {
        return (42, 2);
    }
    

    (警告:如果在 .NET Standard 库中使用值元组,则存在已知问题,因为从 .NET Standard 到 .NET Framework 的程序集绑定......有点麻烦)

  3. 自定义返回类型:

    private Something GetHeight()
    {
        return new Something(42, 2);
    }
    

    (为避免分配,您可能希望在这种情况下将Something 定义为readonly struct

【讨论】:

    【解决方案4】:

    你也可以使用out参数:

    static void Main(string[] args)
    {
      int i, j;
      GetHeight(out i, out j);
    }
    
    public static void GetHeight(out int i1, out int i2)
    {
      i1 = 1;
      i2 = 2;
    }
    

    【讨论】:

      【解决方案5】:

      是的,您可以使用 Tuple

      class Program
        {
          static void Main(string[] args)
          {
            Tuple<int, int> height = GetHeight();
      
            Console.WriteLine(height.Item1 + " - " + height.Item2);
            Console.ReadLine();
          }
      
          private static Tuple<int, int> GetHeight()
          {
            return new Tuple<int, int>(2, 3);
          }
        }
      

      输出:

      2 - 3

      【讨论】:

        猜你喜欢
        • 2020-01-21
        • 2015-12-21
        • 2010-10-08
        • 1970-01-01
        • 2011-01-03
        • 1970-01-01
        • 2010-12-17
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多