【问题标题】:Is there any way that I can simplify the use of multiple "if's" inside one another有什么方法可以简化在彼此内部使用多个“if”
【发布时间】:2020-06-20 06:42:44
【问题描述】:

这是我的意思的一个例子。该代码有效,但我想知道是否有另一种方法可以实现相同的功能:

        if (App.ShowIcons)
        {
            if (App.devIsIOS)
            {
                this.Children.Add(FR1, 0, 0);
                this.Children.Add(GT, 1, 0);
                this.Children.Add(FR2, 2, 0);
            }
            else
            {
                this.Children.Add(FR1, 0, 0);
                this.Children.Add(GT, 1, 0);
                this.Children.Add(CE, 2, 0);
            }
        }
        else
        {
            if (App.devIsIOS)
            {
                this.Children.Add(GT, 0, 0);
                this.Children.Add(FR2, 1, 0);
            }
            else
            {
                this.Children.Add(GT, 0, 0);
                this.Children.Add(CE, 1, 0);
            }
        }

更新:这是我在尝试实现其中一个答案时遇到的问题:

【问题讨论】:

  • 有几种写法。您选择的那个也没有什么特别的问题。您还可以使用基于数据的方法,例如维护一个主表,其中包含每个标志的属性,然后过滤它们以获得正确的列表。或者你可以没有逻辑,而是使用资源文件,并为 iOS 提供不同的文件......那种事情。有无穷无尽的选择。这完全取决于使逻辑尽可能明显且易于维护的原因..
  • LINQ 可以是一个解决方案,后跟 lambda 表达式。
  • 你能给一个LINQ(或其他例子)
  • Children的类型是什么?我想知道Add 做了什么,三个参数是什么意思。

标签: c# if-statement


【解决方案1】:

减少嵌套的一种可能方法是使用元组和开关

switch (ShowIcons, devIsIOS)
{
    case (true, true):
        Children.Add(FR1, 0, 0);
        Children.Add(GT, 1, 0);
        Children.Add(FR2, 2, 0);
        break;
    case (true, false):
        Children.Add(FR1, 0, 0);
        Children.Add(GT, 1, 0);
        Children.Add(CE, 2, 0);
        break;
    case (false, true):
        Children.Add(GT, 0, 0);
        Children.Add(FR2, 1, 0);
        break;
    case (false, false):
        Children.Add(CE, 2, 0);
        Children.Add(GT, 0, 0);
        Children.Add(CE, 1, 0);
        break;
    default:
        throw new Exception("");
}

如果这个逻辑在应用程序中没有被过多地使用,那么可以使用它。但是,如果此逻辑是动态的并且将来会发生变化,那么请尝试以面向对象的方式编写代码并使用多态而不是分支(if-else)来处理逻辑,如blog 所示。

【讨论】:

  • 你能用多态方式记录一个解决方案吗?然后我很乐意接受。谢谢
  • 我举了一些关于政治方法的例子。
  • @Alan2 我无法根据相关信息排除类,这是一个如何将分支转换为类的示例link
【解决方案2】:

从嵌套的if 语句中删除重复调用可以使整个表达式更短更清晰

if (App.ShowIcons)
{
    Children.Add(FR1, 0, 0);
    Children.Add(GT, 1, 0);
    Children.Add(App.devIsIOS ? FR2 : CE, 2, 0);
}
else
{
    Children.Add(GT, 0, 0);
    Children.Add(App.devIsIOS ? FR2 : CE, 1, 0);
}

根据 cmets,如果 FR2CE 值具有不同的类型,则应将它们强制转换为通用基本类型,例如 View 在您的情况下为 Children.Add(App.devIsIOS ? (View)FR2 : CE, 1, 0);

【讨论】:

  • 您好 Pavel,我最喜欢您的解决方案,但遇到了问题。实施后,我在 IDE 中收到一条消息,因为 FR2 和 CE 的类型不同。我已将此消息放在问题中以供查看。你有什么想法可以解决这个问题吗?
  • FR2CEChildren 集合的类型是什么?您有问题的屏幕根本没有帮助。为基类型添加强制转换可以解决它
  • FR2 是 Frame,CE 是 Entry。很抱歉没有提供所有信息。你知道是否有它们共享的任何基本类型,如果有,我该如何做这样的演员?
  • @Alan2 你可以尝试使用基础View 类,类似于Children.Add(App.devIsIOS ? (View)FR2 : CE, 1, 0);
【解决方案3】:

这是一个很难回答的问题,有很多方法可以实现这样的东西,然后就变成了个人喜好问题。

也就是说,这个逻辑可以在不使用嵌套的if/else 子句的情况下简化和实现,我希望标题是你想要的:

var index = 0;
if (App.ShowIcons)
    children.Add(FR1, index++, 0);
children.Add(GT, index++, 0);
children.Add(App.devIsIOS ? FR2 : CE, index, 0);

【讨论】:

    【解决方案4】:

    我喜欢 Mujahid Daud Khan 对使用 C# 8.0 模式的回答。对于多态的方式,我认为这篇文章是 TLDR :P

    在基本层面上,我们可以这样做:

    using System;
    using System.Collections.Generic;
    
    namespace ConsoleApp4
    {
        class Program
        {
            static void Main()
            {
                var builder = new IconSelectorBuilder();
    
                Console.WriteLine($"{nameof(Device.DevIsIOS)}, false");
                foreach (var item in builder.Build(Device.DevIsIOS, false).GetIcons())
                {
                    Console.WriteLine(item);
                }
    
                Console.WriteLine($"{nameof(Device.DevIsIOS)}, true");
                foreach (var item in builder.Build(Device.DevIsIOS, true).GetIcons())
                {
                    Console.WriteLine(item);
                }
    
                //Console.WriteLine($"{nameof(Device.Other)}, false");
                //foreach (var item in builder.Build(Device.Other, false).GetIcons())
                //{
                //    Console.WriteLine(item);
                //}
    
                //Console.WriteLine($"{nameof(Device.Other)}, true");
                //foreach (var item in builder.Build(Device.Other, true).GetIcons())
                //{
                //    Console.WriteLine(item);
                //}
            }
        }
    
        public enum Device
        {
            DevIsIOS,
            Other
        }
    
        public class IconSelectorBuilder
        {
            public IIconSelector Build(Device device, bool showIcons)
            {
                return device switch
                {
                    Device.DevIsIOS => new DevIsIOSIconSelector(showIcons),
                    _ => new OtherIconSelector(showIcons),
                };
            }
        }
    
        public interface IIconSelector
        {
            public bool ShowIcons { get; set; }
    
            IEnumerable<Icon> GetIcons();
        }
    
        public abstract class IconSelectorBase : IIconSelector
        {
            public bool ShowIcons { get; set; }
    
            protected IconSelectorBase(bool showIcons)
            {
                ShowIcons = showIcons;
            }
    
            protected abstract IEnumerable<Icon> GetHideIcons();
    
            protected abstract IEnumerable<Icon> GetShowIcons();
    
            public IEnumerable<Icon> GetIcons() => ShowIcons ? GetShowIcons() : GetHideIcons();
        }
    
    
        public sealed class DevIsIOSIconSelector : IconSelectorBase
        {
            public DevIsIOSIconSelector(bool showIcons) : base(showIcons)
            {
            }
    
            protected override IEnumerable<Icon> GetHideIcons()
            {
                yield return new Icon
                {
                    IconType = IconType.GT,
                    MyProperty1 = 0,
                    MyProperty2 = 0,
                };
    
                yield return new Icon
                {
                    IconType = IconType.FR2,
                    MyProperty1 = 1,
                    MyProperty2 = 0,
                };
            }
    
            protected override IEnumerable<Icon> GetShowIcons()
            {
                yield return new Icon
                {
                    IconType = IconType.FR1,
                    MyProperty1 = 0,
                    MyProperty2 = 0,
                };
    
                yield return new Icon
                {
                    IconType = IconType.GT,
                    MyProperty1 = 1,
                    MyProperty2 = 0,
                };
    
                yield return new Icon
                {
                    IconType = IconType.FR2,
                    MyProperty1 = 2,
                    MyProperty2 = 0,
                };
            }
        }
    
        public sealed class OtherIconSelector : IconSelectorBase
        {
            public OtherIconSelector(bool showIcons) : base(showIcons)
            {
            }
    
            protected override IEnumerable<Icon> GetHideIcons()
            {
                // TODO
                throw new NotImplementedException();
            }
    
            protected override IEnumerable<Icon> GetShowIcons()
            {
                // TODO
                throw new NotImplementedException();
            }
        }
    
        public class Icon
        {
            public IconType IconType { get; set; }
    
            public int MyProperty1 { get; set; }
    
            public int MyProperty2 { get; set; }
    
            public override string ToString() => $"{IconType}, {MyProperty1}, {MyProperty2}";
        }
    
        public enum IconType
        {
            FR1,
            GT,
            FR2,
            CE
        }
    }
    

    这个想法是创建IconSelectorBuilder 并提供App.devIsIOS/whateverApp.ShowIcons/whatever 之类的参数(我假设为布尔值)。然后我们构造一个继承自IconSelectorBase 的适当类,该类为布尔参数(App.ShowIcons/'whatever')提供逻辑。然后适当的类将返回适当的图标。

    输出:

    DevIsIOS, false
    GT, 0, 0
    FR2, 1, 0
    DevIsIOS, true
    FR1, 0, 0
    GT, 1, 0
    FR2, 2, 0
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-06-11
      • 1970-01-01
      • 2021-02-03
      • 1970-01-01
      • 2023-03-08
      • 2010-10-06
      相关资源
      最近更新 更多