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

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


当前回答

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

原文由Anders Kaseorg回答

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

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

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

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

其他回答

为了改进和验证我之前的回答,编程语言术语的定义应该从计算机科学类型理论中解释。

表达式具有除Bottom类型以外的其他类型,即它有一个值。语句具有Unit或Bottom类型。

由此可见,语句只有在产生副作用时才能在程序中发挥作用,因为它要么不能返回值,要么只返回Unit类型的值,而Unit类型的值要么不可赋值(在某些语言中,如C的void),要么可以存储以用于语句的延迟求值。

显然,@pragma或/*comment*/没有类型,因此与语句有所区别。因此,唯一没有副作用的语句类型是非操作。非手术治疗只能作为未来副作用的占位符。由于声明而采取的任何其他行动都是副作用。同样,编译器提示,例如@pragma,不是语句,因为它没有类型。

语句是表达式的一种特殊情况,具有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类型的表达式。

我对这里的答案都不太满意。我查看了c++ (ISO 2008)的语法。然而,出于教学和编程的考虑,答案可能足以区分这两个元素(尽管现实看起来更复杂)。

语句由零个或多个表达式组成,但也可以是其他语言概念。这是语法的扩展巴克斯诺尔形式(语句节选):

statement:
        labeled-statement
        expression-statement <-- can be zero or more expressions
        compound-statement
        selection-statement
        iteration-statement
        jump-statement
        declaration-statement
        try-block

我们可以看到c++中被认为是语句的其他概念。

表达式-语句是自解释的(一个语句可以由0个或多个表达式组成,仔细阅读语法,这很棘手) 例如,Case是一个带标签的语句 选择语句是if if/else, case 迭代语句是while, do…然而,对于(……) 跳转语句有break, continue, return(可以返回表达式),goto Declaration-statement是声明的集合 try-block是表示try/catch块的语句 在语法中可能还有更多

以下是表达部分的节选:

expression:
        assignment-expression
        expression "," assignment-expression
assignment-expression:
        conditional-expression
        logical-or-expression assignment-operator initializer-clause
        throw-expression

表达式通常是或包含赋值 条件表达式(听起来容易误导人)指的是使用运算符(+,-,*,/,&,|,&&,||,…) 抛出表情——呃?throw子句也是一个表达式

声明中,

语句是构造所有c#程序的过程构建块。语句可以声明局部变量或常量,调用方法,创建对象,或为变量、属性或字段赋值。

由花括号括起来的一系列语句构成了一个代码块。方法体就是代码块的一个例子。

bool IsPositive(int number)
{
    if (number > 0)
    {
        return true;
    }
    else
    {
        return false;
    }
}

c#中的语句通常包含表达式。c#中的表达式是包含文字值、简单名称或操作符及其操作数的代码片段。

表达式,

表达式是可以计算为单个值、对象、方法或名称空间的代码片段。最简单的两种表达式是字面量和简单名称。字面量是一个没有名字的常量值。

int i = 5;
string s = "Hello World";

i和s都是用来标识局部变量的简单名称。当在表达式中使用这些变量时,将检索变量的值并将其用于表达式。

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

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

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

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

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

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

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

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

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

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

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

void executeSomething(void){
    return;
}

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

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

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