C#,将 case 语句转换为 yield 语句

C#, converting a case statement to a yield statement

我想使用 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,所以我对它应该如何工作感到困惑。

根据您所说的“期望的最终目标”

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

所有其他 looping/finagling 只是混淆了问题,恕我直言

根据您的定义,

GetLinuxVmDistros() 将 return 变成 IEnumerable<VmDistribution>

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

如果linuxDistrosList<VmDistribution>,只需使用AddRange方法:

linuxDistros.AddRange(GetLinuxVmDistros());

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

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

我不确定你试图实现什么,因为命名是..不清楚。但是使用下面的代码,它可以工作:

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()

在您的示例中,您应该使用循环对项目执行任何需要执行的操作。

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

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

例如,如果出于某种原因无法处理 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
    };