【问题标题】:C#, converting a case statement to a yield statementC#,将 case 语句转换为 yield 语句
【发布时间】:2022-01-01 06:09:08
【问题描述】:

我想使用 yield 关键字将此语句以构建用于测试的 VM 映像列表转换为更优雅的内容,但语法使我难以理解。

期望的最终目标。

List<VmImages> images;
images[0] - WindowsServer2019
images[1] - WindowsServer2016
images[2] - RhelServer;
images[3] - OpenLogic;

今天的代码是这样的:

for (var i = 0; i < LinuxVMs; i++)
{
    switch (i)
    {
        case 0:
            linuxDistros.Add(ConfigLoader.redHat);
            break;
        case 1:
            linuxDistros.Add(ConfigLoader.openLogic);
            break;
        case 2:
            linuxDistros.Add(ConfigLoader.suse);
            break;
        case 3:
            linuxDistros.Add(ConfigLoader.ubuntu);
            break;
    }
}

这感觉像是使用 yield 关键字将逻辑简化成这样的一个很好的例子,我调用 GetLinuxVMs() x 次,其中 X 是 LinuxVMs 的计数。

private static IEnumerable<VmDistribution> GetLinuxVmDistros()
{
    yield return ConfigLoader.redHat;
    yield return ConfigLoader.openLogic;
    yield return ConfigLoader.suse;
    yield return ConfigLoader.canonical;
}

我不确定如何将它集成到我的代码中,这是我尝试过的:

for (var i = 0; i < LinuxVMs; i++)
{
    linuxDistros.Add(GetLinuxVmDistros());
}

由于我每次都从 GetLinuxVmDistros 方法返回一个 IEnum,我对它应该如何工作感到困惑。

【问题讨论】:

  • linuxDistros 的类型是什么?
  • 出于好奇,你为什么需要一个循环和一个 switch 语句来简单地将 4 个值添加到列表中?那可能是 4 行一样。也许坚持下去。
  • 您的代码似乎与您的最终目标不一致
  • 小心,您可以在TheDailyWTF 上结束操作 :-)
  • @HansKesting 那篇文章让我认为我正在尝试的是一个坏主意。感谢您的提示!

标签: c# yield yield-return


【解决方案1】:

根据您声明的“期望的最终目标”

List<VmImages> images = new() {
    WindowsServer2019,
    WindowsServer2016,
    RhelServer,
    OpenLogic
}

所有其余的循环/finagling 只是混淆了这个问题,恕我直言

【讨论】:

    【解决方案2】:

    GetLinuxVmDistros() 将根据您的定义返回 IEnumerable&lt;VmDistribution&gt;

    您似乎想向名为linuxDistros 的集合添加另一个集合。

    如果linuxDistrosList&lt;VmDistribution&gt;,只需使用AddRange 方法:

    linuxDistros.AddRange(GetLinuxVmDistros());
    

    见:https://docs.microsoft.com/fr-fr/dotnet/api/system.collections.generic.list-1.addrange?view=net-6.0

    但我看不到为此创建 Enumerable 的意义。

    【讨论】:

      【解决方案3】:

      我不确定你想达到什么目标,因为命名......不清楚。但是使用下面的代码,它可以工作:

      class ConfigLoader
      {
          static public VmDistribution redHat { get; set; } = VmDistribution.a;
          static public VmDistribution openLogic { get; set; } = VmDistribution.b;
          static public VmDistribution suse { get; set; } = VmDistribution.c;
          static public VmDistribution canonical { get; set; } = VmDistribution.d;
      }
      
      enum VmDistribution { a, b, c, d }
      IEnumerable<VmDistribution> GetLinuxVmDistros()
      {
          yield return ConfigLoader.redHat;
          yield return ConfigLoader.openLogic;
          yield return ConfigLoader.suse;
          yield return ConfigLoader.canonical;
      }
      
      var list = new List<VmDistribution>();
      list.AddRange(GetLinuxVmDistros());
      

      请注意,最后我只调用了一次GetLinuxVmDistros(),并且列表中填充了方法list.AddRange()

      【讨论】:

      • 如果我想调用 GetLinuxVmDistros 两次,我不会得到两个 IEnums 吗?这些不打算像我一样在 for 或 foreach 循环中使用吗?
      • 好吧,当你调用list.AddRange( IEnumerable&lt;&gt; ); 时,后面会发生什么,IEnumerable 将逐个元素地枚举,并将它们全部添加到列表中。如果您在该循环中执行此操作(forwhile、..),您将执行多次。
      【解决方案4】:

      在您的示例中,您应该对带有循环的项目做任何您需要做的事情。

      for (var i = 0; i < LinuxVMs; i++)
      {
          ProcessItem(LinuxVMs[i]);
      }
      

      话虽如此,在这么少的结果集上取得成果并没有多大意义。 yield return 的主要目的是允许一次返回一个大型集合,调用代码可能希望在任何时候停止迭代这些项目。另一种用法是一次获取所有项目可能在资源方面非常昂贵。

      例如,如果由于某种原因无法处理 1 个项目,您可能不想继续。

      for (var i = 0; i < LinuxVMs; i++)
      {
          var result = ProcessItem(LinuxVMs[i]);
          
          if (!result.Success)
          {
              break;
          }
      }
      

      但是,如果您只需要列表中的项目,那么请忘记所有这些,直接创建包含项目的列表:

      var images = 
          new List<VmImages> 
          {
              WindowsServer2019,
              WindowsServer2016,
              RhelServer,
              OpenLogic
          };
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2020-01-24
        • 2022-07-23
        • 2013-07-09
        • 1970-01-01
        • 1970-01-01
        • 2022-01-26
        • 1970-01-01
        相关资源
        最近更新 更多