我问的是关于c#的问题,但我认为它在大多数其他语言中都是一样的。

有人对表达式和语句有很好的定义吗?它们的区别是什么?


当前回答

在面向语句的编程语言中,代码块被定义为语句列表。换句话说,语句是可以放入代码块而不会导致语法错误的一段语法。

维基百科对statement这个词的定义类似

在计算机编程中,语句是命令式编程语言的语法单位,它表示要执行的某些操作。用这种语言编写的程序由一个或多个语句的序列组成

注意后一种说法。(尽管在这种情况下,“一个程序”在技术上是错误的,因为C和Java都拒绝一个不包含任何语句的程序。)

维基百科对表达式的定义是

编程语言中的表达式是一个语法实体,可以对其求值以确定其值

然而,这是错误的,因为在Kotlin中,throw new Exception("")是一个表达式,但当求值时,它只是抛出一个异常,从不返回任何值。

在静态类型编程语言中,每个表达式都有一个类型。然而,这个定义在动态类型编程语言中不起作用。

就我个人而言,我将表达式定义为一段语法,它可以由运算符或函数调用组成,以产生更大的表达式。这其实和维基百科对表达式的解释很相似:

它是一个或多个常量、变量、函数和操作符的组合,编程语言解释(根据其特定的优先级和关联规则)并计算产生(在有状态环境中为“返回”)另一个值

但是,问题是在C编程语言中,给定一个函数执行如下内容:

void executeSomething(void){
    return;
}

executessomething()是表达式还是语句?根据我的定义,它是一个语句,因为根据微软C引用语法的定义,

不能以任何方式使用具有void类型的表达式的(不存在的)值,也不能将void表达式(通过隐式或显式转换)转换为除void以外的任何类型

但同一页明确指出,这样的语法是一个表达式。

其他回答

语句是表达式的一种特殊情况,具有void类型。语言区别对待语句的倾向经常会导致问题,如果恰当地概括它们会更好。

例如,在c#中,我们有非常有用的Func<T1, T2, T3, TResult>重载泛型委托集。但是我们也必须有相应的Action<T1, T2, T3>集合,并且通用的高阶编程必须不断重复来处理这种不幸的分叉。

简单的例子——在调用另一个函数之前检查引用是否为空的函数:

TResult IfNotNull<TValue, TResult>(TValue value, Func<TValue, TResult> func)
                  where TValue : class
{
    return (value == null) ? default(TValue) : func(value);
}

编译器能处理TResult为空的可能性吗?是的。它所要做的就是要求return后面跟着一个void类型的表达式。default(void)的结果将是void类型,传递的func将需要是func <TValue, void>(这将等效于Action<TValue>)的形式。

其他一些答案暗示你不能像连接表达式那样连接语句,但我不确定这个想法是从哪里来的。我们可以想到;它作为二进制中缀运算符出现在语句之后,取void类型的两个表达式并将它们组合成一个void类型的表达式。

下面是我找到的一个最简单的答案。

原文由Anders Kaseorg回答

语句是执行某些操作的完整代码行,而表达式是代码中求值的任何部分。

可以使用操作符将表达式“水平”组合成更大的表达式,而语句只能通过一个接一个地写入或使用块结构来“垂直”组合。

每个表达式都可以用作语句(其效果是计算表达式并忽略结果值),但大多数语句不能用作表达式。

http://www.quora.com/Python-programming-language-1/Whats-the-difference-between-a-statement-and-an-expression-in-Python

表达式可以求值得到一个值,而语句不返回值(它们是void类型)。

当然,函数调用表达式也可以被视为语句,但除非执行环境有一个特殊的内置变量来保存返回值,否则无法检索它。

面向语句的语言要求所有过程都是语句列表。面向表达式的语言,可能是所有的函数式语言,都是表达式的列表,或者在LISP的情况下,是一个表示表达式列表的长s表达式。

尽管这两种类型都可以组合,但只要类型匹配,大多数表达式都可以任意组合。每种类型的语句都有自己的方式来组合其他语句,如果它们可以做到这一切的话。Foreach和if语句要么要求单个语句,要么要求所有子语句一个接一个地放入语句块中,除非子语句允许它们自己的子语句。

语句还可以包括表达式,而表达式实际上不包括任何语句。不过,lambda表达式是一个例外,它表示一个函数,因此可以包括函数可以包含的任何东西,除非语言只允许有限的lambdas,比如Python的单表达式lambdas。

在基于表达式的语言中,你所需要的只是一个函数的单个表达式,因为所有的控制结构都返回一个值(其中很多返回NIL)。不需要return语句,因为函数中最后求值的表达式就是返回值。

表达式是返回值的东西,而语句则不是。

例子:

1 + 2 * 4 * foo.bar()     //Expression
foo.voidFunc(1);          //Statement

两者之间的重要之处在于,您可以将表达式链接在一起,而语句则不能被链接。

我更喜欢“陈述”这个词的形式逻辑意义。它改变了计算中一个或多个变量的状态,从而能够对它们的值做出真或假的声明。

我想,当新的术语或词汇被引入,现有的词汇被“重新定义”,或者用户对他们所描述的现有的、已建立的或“适当的”术语一无所知时,在计算世界和科学中总会出现困惑