C# 表达式语法详解
C# 表达式(Expression)是C#语言中最重要的组成部分之一,它用于计算值、执行操作或产生副作用。本文将全面深入地介绍C#中各种表达式的语法、用法和特性。
一、表达式基础
1.1 表达式的定义
表达式是由操作数、运算符和分隔符组成的序列,用于计算值或执行操作。表达式可以简单到一个字面量,也可以复杂到包含多个子表达式。
1.2 表达式的类型
C#中的表达式可以分为以下几类:
- 常量表达式:计算结果为常量的表达式
- 布尔表达式:计算结果为布尔值的表达式
- 关系表达式:比较两个值的表达式
- 算术表达式:执行算术运算的表达式
- 逻辑表达式:执行逻辑运算的表达式
- 成员访问表达式:访问对象成员的表达式
- 方法调用表达式:调用方法或委托的表达式
- Lambda表达式:匿名函数的表达式
- 查询表达式:LINQ查询的表达式
- 其他表达式:如new表达式、typeof表达式等
二、常量表达式
常量表达式是在编译时就能确定其值的表达式。
2.1 字面量
int a = 10; // 整数字面量
double b = 3.14; // 双精度浮点数字面量
char c = 'A'; // 字符字面量
string s = "Hello"; // 字符串字面量
bool flag = true; // 布尔字面量
2.2 常量声明
const int MaxValue = 100;
const double Pi = 3.1415926;
2.3 常量表达式示例
const int a = 5;
const int b = 10;
const int sum = a + b; // 常量表达式
三、算术表达式
算术表达式用于执行基本的数学运算。
3.1 基本运算符
运算符 | 描述 | 示例 |
---|---|---|
+ | 加法 | a + b |
- | 减法 | a - b |
* | 乘法 | a * b |
/ | 除法 | a / b |
% | 取模 | a % b |
3.2 复合赋值运算符
运算符 | 描述 | 示例 |
---|---|---|
+= | 加并赋值 | a += b |
-= | 减并赋值 | a -= b |
*= | 乘并赋值 | a *= b |
/= | 除并赋值 | a /= b |
%= | 取模并赋值 | a %= b |
3.3 算术表达式示例
int a = 10;
int b = 3;
int sum = a + b; // 13
int difference = a - b; // 7
int product = a * b; // 30
int quotient = a / b; // 3
int remainder = a % b; // 1
四、关系表达式和布尔表达式
4.1 关系运算符
运算符 | 描述 | 示例 |
---|---|---|
== | 等于 | a == b |
!= | 不等于 | a != b |
> | 大于 | a > b |
< | 小于 | a < b |
>= | 大于等于 | a >= b |
<= | 小于等于 | a <= b |
4.2 逻辑运算符
运算符 | 描述 | 示例 |
---|---|---|
&& | 逻辑与 | a && b |
|| | 逻辑或 | a || b |
! | 逻辑非 | !a |
4.3 布尔表达式示例
int a = 10;
int b = 20;
bool isEqual = a == b; // false
bool isGreater = a > b; // false
bool isLess = a < b; // true
bool andResult = (a > 5) && (b < 30); // true
bool orResult = (a > 15) || (b < 25); // true
bool notResult = !(a == b); // true
五、成员访问表达式
成员访问表达式用于访问对象的成员(字段、属性、方法等)。
5.1 简单成员访问
class Person
{
public string Name { get; set; }
public int Age { get; set; }
}
Person person = new Person { Name = "Alice", Age = 30 };
string name = person.Name; // 访问属性
int age = person.Age; // 访问属性
5.2 方法调用
class Calculator
{
public int Add(int a, int b) => a + b;
}
Calculator calc = new Calculator();
int sum = calc.Add(5, 3); // 方法调用
5.3 索引器访问
class ArrayWrapper
{
private int[] array = { 1, 2, 3, 4, 5 };
public int this[int index] => array[index];
}
ArrayWrapper wrapper = new ArrayWrapper();
int value = wrapper[2]; // 索引器访问
六、Lambda表达式
Lambda表达式是一种匿名函数,用于简化委托和表达式树的创建。
(参数列表) => 表达式或语句块
6.2 示例
// 无参数
Func<int> getFive = () => 5;
// 单参数
Func<int, int> square = x => x * x;
// 多参数
Func<int, int, int> add = (x, y) => x + y;
// 语句块
Action<string> greet = name =>
{
Console.WriteLine($"Hello, {name}!");
};
6.3 类型推断
var multiply = (int x, int y) => x * y; // 类型可以显式指定
var divide = (x, y) => x / y; // 类型可以推断
七、查询表达式(LINQ)
查询表达式是LINQ的核心,用于查询各种数据源。
7.1 基本语法
from 变量 in 数据源
[where 条件]
[orderby 排序]
[select 投影]
[group 分组]
[join 连接]
7.2 示例
List<int> numbers = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
// 查询偶数
var evenNumbers = from n in numbers
where n % 2 == 0
select n;
// 查询并按降序排序
var sortedNumbers = from n in numbers
orderby n descending
select n;
// 分组
var grouped = from n in numbers
group n by n % 2 == 0 into g
select new { IsEven = g.Key, Numbers = g };
八、方法组转换表达式
方法组转换表达式用于将方法组转换为委托类型。
8.1 示例
class Calculator
{
public int Add(int a, int b) => a + b;
}
Calculator calc = new Calculator();
// 方法组转换
Func<int, int, int> addDelegate = calc.Add;
int sum = addDelegate(5, 3); // 调用委托
九、对象创建表达式
对象创建表达式用于创建新对象。
9.1 对象初始化器
class Person
{
public string Name { get; set; }
public int Age { get; set; }
}
// 对象初始化器
Person person = new Person { Name = "Alice", Age = 30 };
9.2 匿名对象
var anonymous = new { Name = "Bob", Age = 25 };
Console.WriteLine(anonymous.Name); // Bob
十、类型表达式
类型表达式用于表示类型本身。
10.1 typeof表达式
Type type = typeof(int);
Console.WriteLine(type.Name); // Int32
10.2 sizeof表达式
int size = sizeof(int); // 4 (在32位系统上)
十一、条件表达式
条件表达式用于根据条件选择值。
11.1 三元运算符
int a = 10;
int b = 20;
int max = (a > b) ? a : b; // 20
11.2 空合并运算符
string name = null;
string displayName = name ?? "Guest"; // "Guest"
十二、其他表达式
12.1 checked和unchecked表达式
// checked表达式
int checkedResult = checked(2147483647 + 1); // 抛出OverflowException
// unchecked表达式
int uncheckedResult = unchecked(2147483647 + 1); // -2147483648
12.2 默认值表达式
int? nullableInt = null;
int value = nullableInt ?? 0; // 0
十三、表达式树
表达式树用于表示代码的逻辑结构,可以在运行时分析和修改。
13.1 创建表达式树
using System.Linq.Expressions;
Expression<Func<int, int>> expr = x => x * x;
13.2 编译和执行表达式树
Func<int, int> func = expr.Compile();
int result = func(5); // 25
十四、综合示例
14.1 复杂表达式示例
using System;
using System.Collections.Generic;
using System.Linq;
class Program
{
static void Main()
{
// 数据源
List<Employee> employees = new List<Employee>
{
new Employee { Id = 1, Name = "Alice", Department = "HR", Salary = 5000 },
new Employee { Id = 2, Name = "Bob", Department = "IT", Salary = 7000 },
new Employee { Id = 3, Name = "Charlie", Department = "IT", Salary = 8000 },
new Employee { Id = 4, Name = "David", Department = "Finance", Salary = 6000 }
};
// 查询表达式
var highSalaryIT = from e in employees
where e.Department == "IT" && e.Salary > 6500
orderby e.Salary descending
select e;
// Lambda表达式
Func<Employee, bool> isHighSalaryIT = e => e.Department == "IT" && e.Salary > 6500;
var highSalaryIT2 = employees.Where(isHighSalaryIT).OrderByDescending(e => e.Salary);
// 方法组转换
Func<Employee, int> getSalary = e => e.Salary;
var salaries = employees.Select(getSalary);
// 输出结果
Console.WriteLine("查询表达式结果:");
foreach (var emp in highSalaryIT)
{
Console.WriteLine($"{emp.Name}: {emp.Salary}");
}
Console.WriteLine("\nLambda表达式结果:");
foreach (var emp in highSalaryIT2)
{
Console.WriteLine($"{emp.Name}: {emp.Salary}");
}
}
}
class Employee
{
public int Id { get; set; }
public string Name { get; set; }
public string Department { get; set; }
public int Salary { get; set; }
}
十五、最佳实践
- 保持表达式简洁:避免过于复杂的嵌套表达式
- 使用有意义的变量名:特别是在LINQ查询中
- 考虑性能:对于大数据集,注意查询表达式的性能影响
- 合理使用方法组转换:提高代码可读性
- 注意类型安全:特别是在使用泛型表达式时
十六、总结
C#中的表达式是构建程序逻辑的基础,掌握各种表达式的语法和用法对于编写高效、可维护的代码至关重要。本文详细介绍了C#中的各种表达式类型,包括算术表达式、关系表达式、成员访问表达式、Lambda表达式、查询表达式等,并通过综合示例展示了它们的实际应用。