热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

C#学习教程:只使用’ifelse’语句的’else’部分是否可以接受?分享

只使用’if-else’语句的’else’部分是否可以接受?有时,我觉得检查所有条件是否都是真的更容易,但是只处理“其他”情况。我想

只使用’if-else’语句的’else’部分是否可以接受?

有时,我觉得检查所有条件是否都是真的更容易,但是只处理“其他”情况。

我想我有时会觉得更容易知道某些东西是有效的,并假设所有其他情况都无效。

例如,假设我们只在出现问题时才真正关心:

object value = GetValueFromSomeAPIOrOtherMethod(); if((value != null) && (!string.IsNullOrEmpty(value.Prop)) && (possibleValues.Contains(value.prop))) { // All the conditions passed, but we don't actually do anything } else { // Do my stuff here, like error handling } 

或者我应该改变它:

 object value = GetValueFromSomeAPIOrOtherMethod(); if((value == null) || (string.IsNullOrEmpty(value.Prop)) || (!possibleValues.Contains(value.prop))) { // Do my stuff here, like error handling } 

或者(我觉得很难看):

 object value = GetValueFromSomeAPIOrOtherMethod(); if(!((value != null) && (!string.IsNullOrEmpty(value.Prop)) && (possibleValues.Contains(value.prop)))) { // Do my stuff here, like error handling } 

虽然对我来说很少见,但我有时会觉得以这种forms写作会在某些情况下产生最清晰的代码。 寻找提供最清晰的表格。 编译器不关心,并且应该基本上(可能确切地)生成相同的代码。

但是,可能更清楚的是,定义一个在if()语句中赋值的布尔变量,然后将代码写为该变量的否定:

 bool myCOndition= (....); if (!myCondition) { ... } 

在else中使用带有语句的空if块是……只是糟糕的样式。 对不起,这是我的一个小小的烦恼。 它没有任何function上的错误,只是让我的眼睛流血。

简单! 输出if语句并将代码放在那里。 恕我直言,它降低了噪音,使代码更具可读性。

我应该先说这是我个人的偏好,但我发现自己通常会将validation逻辑从代码中拉出来并进入自己的validation函数。 那时,你的代码变得更加“整洁”,只需说:

 if(!ValidateAPIValue(value)) 

在我看来,这似乎更简洁,更容易理解。

只使用else部分是不可接受的。 你不必去应用De-Morgan的规则,而不是整个表达。 也就是说,从if (cond)转到if (!(cond))

我认为这是完全不可接受的。

唯一的理由是避免表达式周围的单个否定和括号。 我同意你的例子中的表达是可怕的,但它们开始时是不可接受的错综复杂的! 将表达式划分为可接受的清晰度部分,将它们存储到布尔值中(或者从它们中创建方法),并将它们组合起来以形成if语句条件。

我经常使用的一个类似设计是早退出。 我不写这样的代码:

 if (validityCheck1) { if (validityCheck2) { // Do lots and lots of things } else { // Throw some exception, return something, or do some other simple cleanup/logic (version 2) } } else { // Throw some exception, return something, or do some other simple cleanup/logic. (version 1) } 

相反,我写这个:

 if (!validityCheck1) { // Throw some exception, return false, or do some other simple logic. (version 1) } if (!validityCheck2) { // Throw some exception, return false, or do some other simple logic. (version 2) } // Do lots and lots of things 

这有两个好处:

  1. 只有少数输入案例无效,并且处理简单。 它们应该立即处理,以便我们尽快将它们从我们的心理模型中删除,并完全专注于重要的逻辑。 特别是当嵌套的if语句中存在多个有效性检查时。

  2. 处理有效案例的代码块通常是方法的最大部分,并包含自己的嵌套块。 如果这个代码块本身不在if语句中嵌套(可能多次),那就不那么混乱了。

因此代码更易读,更容易推理。

提取你的条件,然后打电话

 if(!ConditionsMetFor(value)) { //Do Something } 

虽然这并不总是实用,但我通常更愿意改变

 if (complexcondition){} else {/*stuff*/} 

 if (complexcondition) continue; /*stuff*/ 

(或者以returnbreak等方式break )。 当然,如果条件过于复杂,您可以用几个条件替换它,所有条件都会导致代码突破它正在做的事情。 这主要适用于validation和错误检查类型的代码,如果出现问题,您可能想要退出。

如果我看到“如果”,我希望它能做点什么。

 if(!condition) 

更具可读性。

 if(condition) { //do nothing } else { //do stuff } 

本质上是读“如果我的病情得到满足,什么也不做,否则做点什么。”

如果我们要将你的代码作为散文阅读(那些好的,自我记录的代码应该能够以这种方式阅读) ,这太简单了,并且引入了超出实现目标所必需的概念。 坚持使用“!”。

这是不好的风格,考虑一些非常有用的替代方案:

使用保护条款样式

 object value = GetValueFromSomeAPIOrOtherMethod(); if((value != null) && (!string.IsNullOrEmpty(value.Prop)) && (possibleValues.Contains(value.prop))) { return; } // do stuff here 

将条件提取到自己的方法中,这使事情保持逻辑且易于阅读:

 bool ValueHasProperty(object value) { return (value != null) && (!string.IsNullOrEmpty(value.Prop)) && (possibleValues.Contains(value.prop)); } void SomeMethod() { object value = GetValueFromSomeAPIOrOtherMethod(); if(!ValueHasProperty(value)) { // do stuff here } } 

你的问题类似于我最喜欢的程序员无知宠物的答案(简化条件)

对于不支持until结构的语言,链接多个NOT会使我们的眼睛流血

哪一个更容易阅读?

这个:

 while (keypress != escape_key && keypress != alt_f4_key && keypress != ctrl_w_key) 

或这个:

 until (keypress == escape_key || keypress == alt_f4_key || keypress == ctrl_w_key) 

我认为后者比第一个更容易理解。 第一个涉及太多的NOT和AND条件使逻辑更 ,它会强制您在确定您的代码确实正确之前读取整个表达式,如果您的逻辑涉及到它将更难读复杂的逻辑(需要链接更多的AND,非常粘稠)。

大学期间,德摩根定理在我们class上讲授。 我真的很感激使用他的定理可以简化逻辑。 因此对于直到语句不支持的语言构造,请使用:

 while !(keypress == escape_key || keypress == alt_f4_key || keypress == ctrl_w_key) 

但由于C不支持无括号while / if语句,我们需要在DeMorgan代码上添加括号:

 while (!(keypress == escape_key || keypress == alt_f4_key || keypress == ctrl_w_key)) 

而那可能促使Dan C评论说DeMorgan的代码更多地依赖于我最喜欢的程序员无知宠物的答案。

但实际上,DeMorgan代码比拥有多个NOTS和粘性AND更容易阅读

[编辑]

你的代码(DeMorgan’d):

 object value = GetValueFromSomeAPIOrOtherMethod(); if ( value == null || string.IsNullOrEmpty(value.Prop) || !possibleValues.Contains(value.prop) ) { // Do my stuff here, like error handling } 

..完全没问题。 事实上,大多数程序员(特别是那些没有try / catch / finally结构的语言)确实满足条件(例如,不使用空指针,具有适当的值等)在继续操作之前。

注意:我冒昧地删除了代码中多余的括号,也许你来自Delphi / Pascal语言。

当我的大脑能够轻松地将自己包裹在成功的逻辑中时,我就会这样做,但是理解失败的逻辑是很麻烦的。

我通常只是发表评论“// no op”,所以人们都知道这不是一个错误。

这不是一个好习惯。 如果你使用ruby你会做:

 unless condition do something end 

如果你的语言不允许这样做,而不是做

 if(a){}else{something} 

 if(!a){something} 

我发现它是不可接受的(尽管我确定我已经在过去做过)有一个像这样的空块。 这意味着应该做点什么。

我看到其他问题表明它的第二种方式更具可读性。 就个人而言,我说你的例子都不是特别易读。 您提供的示例是请求“IsValueValid(…)”方法。

我偶尔会发现自己处于相关但略有不同的情况:

 if ( TheMainThingIsNormal () ) ; // nothing special to do else if ( SomethingElseIsSpecial () ) // only possible/meaningful if ! TheMainThingIsNormal () DoSomethingSpecial (); else if ( TheOtherThingIsSpecial () ) DoSomethingElseSpecial (); else // ... you see where I'm going here // and then finish up 

取出空块的唯一方法是创建更多嵌套:

 if ( ! TheMainThingIsNormal () ) { if ( SomethingElseIsSpecial () ) DoSomethingSpecial (); else if ( TheOtherThingIsSpecial () ) DoSomethingElseSpecial (); else // ... } 

我没有检查exception或validation条件 – 我只是处理特殊情况或一次性情况 – 所以我不能提前纾困。

我的答案通常都是不…但我认为良好的编程风格是基于一致性…..

所以如果我有很多看起来像的表情

 if (condition) { // do something } else { // do something else } 

然后偶尔“空”if块是好的,例如

 if (condition) { } // do nothing else { // do something else } 

这样做的原因是,如果你的眼睛看到几次,他们就不太可能注意到变化,例如微小的“!”。 因此即使孤立地做一件坏事,它很可能会让某人在未来维护代码时意识到这个特殊的if..else ……与其他人不同……

可能可接受的其他特定场景是某种状态机逻辑,例如

 if (!step1done) {} // do nothing, but we might decide to put something in here later else if (!step2done) { // do stuff here } else if (!step3done) { // do stuff here } 

这显然突出了状态的顺序流动,每个阶段执行的步骤(即使它什么都没有)。 我更喜欢它…

 if (step1done && !step2Done) { // do stuff here } if (step1done && step2done && !state3Done) { // do stuff here } 

我喜欢第二个版本。 它使代码更干净。 实际上,这是我在代码审查期间要求纠正的事情之一。

为了便于阅读,我总是尝试将这样的大条件重构为属性或方法。 所以这:

 object value = GetValueFromSomeAPIOrOtherMethod(); if((value == null) || (string.IsNullOrEmpty(value.Prop)) || (!possibleValues.Contains(value.prop))) { // Do my stuff here, like error handling } 

变得像这样:

 object value = GetValueFromSomeAPIOrOtherMethod(); if (IsValueUnacceptable(value)) { // Do my stuff here, like error handling } ... ///  /// Determines if the value is acceptable. ///  /// The value to criticize. private bool IsValueUnacceptable(object value) { return (value == null) || (string.IsNullOrEmpty(value.Prop)) || (!possibleValues.Contains(value.prop)) } 

现在,您可以随时重用方法/属性,并且您不必在使用方法中考虑太多。

当然,IsValueUnacceptable可能是一个更具体的名称。

第一名:

 object value = GetValueFromSomeAPIOrOtherMethod(); var isValidValue = (value != null) && (!string.IsNullOrEmpty(value.Prop)) && (possibleValues.Contains(value.prop)); if(!isValidValue) { // Do my stuff here, like error handling } 

2cnd:

 object value = GetValueFromSomeAPIOrOtherMethod(); if(!isValidAPIValue(value)) { // Do my stuff here, like error handling } 

所有的表达方式都一样吗? 在支持短路的语言中,在ands和ors之间进行更改可能是致命的。 记住&&作为警卫使用,以防止其他条件被检查。

转换时要小心。 犯了比你想象的更多的错误。

在这些情况下,您可能希望将validation逻辑抽象到类本身中,以帮助解决应用程序代码的混乱问题。

例如

 class MyClass { public string Prop{ get; set; } // ... snip ... public bool IsValid { bool valid = false; if((value != null) && (!string.IsNullOrEmpty(value.Prop)) && (possibleValues.Contains(value.prop))) { valid = true } return valid; } // ...snip... } 

现在你的应用代码

 MyClass = value = GetValueFromSomewhere(); if( value.IsValie == false ) { // Handle bad case here... } 

我是DeMorgan规则的粉丝,它带你的ex3并产生你的ex2。 空if块是一个心理块imo。 你必须停下来阅读存在的任何东西 – 然后你不得不想知道为什么。

如果你必须留下像//这样的评论。 然后代码不是很明显。

如果你不需要写if块你需要把(!)’not’in if block ..no,那么下面的样式让一个块空了if-else被认为是一种糟糕的风格..对于良好的编程实践需要写别的

如果(条件)//空白其他//代码

可以替换为

if(!condition)//代码

这是节省额外的代码行也..

我不会在C#中这样做。 但是我在Python中这样做,因为Python有一个关键字意味着“不做任何事情”:

 if primary_condition: pass elif secondary_condition1: do_one_thing() elif secondary_condition2: do_another_thing() 

你可以说{ }在function上等同于pass ,它就是。 但它(不是人类)在语义上是等价的。 pass意味着“什么都不做”,而对我来说, { }通常意味着“这里曾经有过代码而现在却没有。”

但总的来说,如果我到达甚至是一个问题是否坚持! 在条件面前让人难以阅读,我遇到了问题。 如果我发现自己编写这样的代码:

 while (keypress != escape_key && keypress != alt_f4_key && keypress != ctrl_w_key) 

我很清楚,从长远来看,我真正想要的是这样的:

 var activeKeys = new[] { escape_key, alt_f4_key, ctrl_w_key }; while (!activeKeys.Contains(keypress)) 

因为这明确了一个概念(“这些键是活动的”),它只隐含在前面的代码中,并使逻辑“这就是你按下非活动键时发生的事情”,而不是“这就是当一个键发生时会发生什么没有一个ESC,ALT + F4或CTRL + W被按下。“

上述就是C#学习教程:只使用’if-else’语句的’else’部分是否可以接受?分享的全部内容,如果对大家有所用处且需要了解更多关于C#学习教程,希望大家多多关注—编程笔记


推荐阅读
  • 利用Visual Basic开发SAP接口程序初探的方法与原理
    本文介绍了利用Visual Basic开发SAP接口程序的方法与原理,以及SAP R/3系统的特点和二次开发平台ABAP的使用。通过程序接口自动读取SAP R/3的数据表或视图,在外部进行处理和利用水晶报表等工具生成符合中国人习惯的报表样式。具体介绍了RFC调用的原理和模型,并强调本文主要不讨论SAP R/3函数的开发,而是针对使用SAP的公司的非ABAP开发人员提供了初步的接口程序开发指导。 ... [详细]
  • Android Studio Bumblebee | 2021.1.1(大黄蜂版本使用介绍)
    本文介绍了Android Studio Bumblebee | 2021.1.1(大黄蜂版本)的使用方法和相关知识,包括Gradle的介绍、设备管理器的配置、无线调试、新版本问题等内容。同时还提供了更新版本的下载地址和启动页面截图。 ... [详细]
  • 本文介绍了lua语言中闭包的特性及其在模式匹配、日期处理、编译和模块化等方面的应用。lua中的闭包是严格遵循词法定界的第一类值,函数可以作为变量自由传递,也可以作为参数传递给其他函数。这些特性使得lua语言具有极大的灵活性,为程序开发带来了便利。 ... [详细]
  • Python实现变声器功能(萝莉音御姐音)的方法及步骤
    本文介绍了使用Python实现变声器功能(萝莉音御姐音)的方法及步骤。首先登录百度AL开发平台,选择语音合成,创建应用并填写应用信息,获取Appid、API Key和Secret Key。然后安装pythonsdk,可以通过pip install baidu-aip或python setup.py install进行安装。最后,书写代码实现变声器功能,使用AipSpeech库进行语音合成,可以设置音量等参数。 ... [详细]
  • 开发笔记:加密&json&StringIO模块&BytesIO模块
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了加密&json&StringIO模块&BytesIO模块相关的知识,希望对你有一定的参考价值。一、加密加密 ... [详细]
  • 本文介绍了Redis的基础数据结构string的应用场景,并以面试的形式进行问答讲解,帮助读者更好地理解和应用Redis。同时,描述了一位面试者的心理状态和面试官的行为。 ... [详细]
  • 原文地址:https:www.cnblogs.combaoyipSpringBoot_YML.html1.在springboot中,有两种配置文件,一种 ... [详细]
  • 本文介绍了Hyperledger Fabric外部链码构建与运行的相关知识,包括在Hyperledger Fabric 2.0版本之前链码构建和运行的困难性,外部构建模式的实现原理以及外部构建和运行API的使用方法。通过本文的介绍,读者可以了解到如何利用外部构建和运行的方式来实现链码的构建和运行,并且不再受限于特定的语言和部署环境。 ... [详细]
  • 使用在线工具jsonschema2pojo根据json生成java对象
    本文介绍了使用在线工具jsonschema2pojo根据json生成java对象的方法。通过该工具,用户只需将json字符串复制到输入框中,即可自动将其转换成java对象。该工具还能解析列表式的json数据,并将嵌套在内层的对象也解析出来。本文以请求github的api为例,展示了使用该工具的步骤和效果。 ... [详细]
  • C# 7.0 新特性:基于Tuple的“多”返回值方法
    本文介绍了C# 7.0中基于Tuple的“多”返回值方法的使用。通过对C# 6.0及更早版本的做法进行回顾,提出了问题:如何使一个方法可返回多个返回值。然后详细介绍了C# 7.0中使用Tuple的写法,并给出了示例代码。最后,总结了该新特性的优点。 ... [详细]
  • 计算机存储系统的层次结构及其优势
    本文介绍了计算机存储系统的层次结构,包括高速缓存、主存储器和辅助存储器三个层次。通过分层存储数据可以提高程序的执行效率。计算机存储系统的层次结构将各种不同存储容量、存取速度和价格的存储器有机组合成整体,形成可寻址存储空间比主存储器空间大得多的存储整体。由于辅助存储器容量大、价格低,使得整体存储系统的平均价格降低。同时,高速缓存的存取速度可以和CPU的工作速度相匹配,进一步提高程序执行效率。 ... [详细]
  • 本文介绍了计算机网络的定义和通信流程,包括客户端编译文件、二进制转换、三层路由设备等。同时,还介绍了计算机网络中常用的关键词,如MAC地址和IP地址。 ... [详细]
  • CF:3D City Model(小思维)问题解析和代码实现
    本文通过解析CF:3D City Model问题,介绍了问题的背景和要求,并给出了相应的代码实现。该问题涉及到在一个矩形的网格上建造城市的情景,每个网格单元可以作为建筑的基础,建筑由多个立方体叠加而成。文章详细讲解了问题的解决思路,并给出了相应的代码实现供读者参考。 ... [详细]
  • C++字符字符串处理及字符集编码方案
    本文介绍了C++中字符字符串处理的问题,并详细解释了字符集编码方案,包括UNICODE、Windows apps采用的UTF-16编码、ASCII、SBCS和DBCS编码方案。同时说明了ANSI C标准和Windows中的字符/字符串数据类型实现。文章还提到了在编译时需要定义UNICODE宏以支持unicode编码,否则将使用windows code page编译。最后,给出了相关的头文件和数据类型定义。 ... [详细]
  • Go Cobra命令行工具入门教程
    本文介绍了Go语言实现的命令行工具Cobra的基本概念、安装方法和入门实践。Cobra被广泛应用于各种项目中,如Kubernetes、Hugo和Github CLI等。通过使用Cobra,我们可以快速创建命令行工具,适用于写测试脚本和各种服务的Admin CLI。文章还通过一个简单的demo演示了Cobra的使用方法。 ... [详细]
author-avatar
Owi妓l_972
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有