C#语法查缺补漏
C#语法补充
空条件运算符和空合并运算符
var clientIp = context.HttpContext.Connection.RemoteIpAddress?.ToString() ?? "unknown";
- 首先RemoteIpAddress允许为空
- 若这个表达式(context.HttpContext.Connection.RemoteIpAddress?.ToString())值为null,则返回右边的值
- 类似的语法模式如下
// 示例1:处理可能为null的配置值
var connectionString = Configuration.GetSection("ConnectionStrings:Default")?.Value ?? "DefaultConnection";
// 示例2:处理可能为null的用户输入
var userName = user?.Name ?? "匿名用户";
// 示例3:处理可能为null的集合
var firstItem = items?.FirstOrDefault() ?? defaultItem;
值类型和引用类型的区别
值类型 (Value Types)
特点:
- 直接存储数据本身
- 分配在栈(stack)上(但作为类成员时随对象在堆上)
- 赋值时复制整个值
- 不能为null(除非使用可空类型)
主要分类:
// 1. 基本数值类型
int number = 10;
double price = 99.99;
bool flag = true;
char character = 'A';
// 2. 结构体 (struct)
struct Point
{
public int X;
public int Y;
}
// 3. 枚举 (enum)
enum Color { Red, Green, Blue }
引用类型 (Reference Types)
特点:
- 存储的是内存地址引用
- 分配在堆(heap)上
- 赋值时复制引用,而不是数据本身
- 可以为null
主要分类:
// 1. 类 (class)
class Person
{
public string Name;
public int Age;
}
// 2. 接口 (interface)
interface IAnimal
{
void Speak();
}
// 3. 数组
int[] numbers = new int[5];
string[] names = new string[3];
// 4. 委托 (delegate)
delegate void MyDelegate(string message);
// 5. 字符串
string text = "Hello World";
核心区别
1. 内存分配和存储
// 值类型示例
int a = 10;
int b = a; // 复制值
b = 20; // 不影响a
Console.WriteLine(a); // 输出: 10
// 引用类型示例
Person p1 = new Person { Name = "John" };
Person p2 = p1; // 复制引用
p2.Name = "Jane"; // 影响p1
Console.WriteLine(p1.Name); // 输出: Jane
2. 参数传递行为
void ModifyValue(int value) => value = 100;
void ModifyReference(Person person) => person.Name = "Modified";
int num = 50;
Person person = new Person { Name = "Original" };
ModifyValue(num); // num不变,还是50
ModifyReference(person); // person.Name变成"Modified"
3. 默认值不同
int defaultInt; // 0
bool defaultBool; // false
Person defaultPerson; // null
4. 相等比较
// 值类型比较内容
int x = 5, y = 5;
Console.WriteLine(x == y); // True
// 引用类型默认比较引用
Person p1 = new Person { Name = "Tom" };
Person p2 = new Person { Name = "Tom" };
Console.WriteLine(p1 == p2); // False(除非重写==运算符)
特殊情况和注意事项
1. 装箱和拆箱 (Boxing/Unboxing)
// 装箱:值类型 → 引用类型
int value = 42;
object boxed = value; // 装箱
// 拆箱:引用类型 → 值类型
int unboxed = (int)boxed; // 拆箱
2. ref 关键字
void ModifyWithRef(ref int value) => value = 100;
int number = 50;
ModifyWithRef(ref number);
Console.WriteLine(number); // 输出: 100
3. 可空值类型
int? nullableInt = null; // 等价于 Nullable<int>
DateTime? nullableDate = null;
性能考虑
- 值类型:栈分配,快速,无GC压力
- 引用类型:堆分配,需要GC管理,有开销
选择指南
使用值类型当:
- 类型表示单个值
- 实例大小较小(通常<16字节)
- 不需要继承
- 希望避免堆分配
使用引用类型当:
- 类型是复杂对象
- 需要继承和多态
- 实例可能很大
- 需要共享引用
理解这两种类型的区别对于编写高效、正确的C#代码至关重要,特别是在处理性能敏感场景时。
表达式体
- 只读属性
// 传统写法
public int TemperatureF
{
get { return 32 + (int)(TemperatureC / 0.5556); }
}
// 表达式体写法(更简洁)
public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
- 只读属性计算
public class Rectangle
{
public double Width { get; set; }
public double Height { get; set; }
// 计算面积
public double Area => Width * Height;
// 计算周长
public double Perimeter => 2 * (Width + Height);
// 判断是否为正方形
public bool IsSquare => Width == Height;
}
- 属性访问器
public class Student
{
private string _name;
public string Name
{
get => _name;
set => _name = value ?? throw new ArgumentNullException(nameof(value));
}
private int _age;
public int Age
{
get => _age;
set => _age = value >= 0 ? value : throw new ArgumentException("年龄不能为负数");
}
}
- 方法中的表达式体
public class Calculator
{
// 传统方法
public int Add(int a, int b)
{
return a + b;
}
// 表达式体方法
public int Add(int a, int b) => a + b;
public double Divide(double x, double y) => y != 0 ? x / y : 0;
}
- 构造函数和析构函数
public class Person
{
public string FirstName { get; }
public string LastName { get; }
// 表达式体构造函数
public Person(string firstName, string lastName) =>
(FirstName, LastName) = (firstName, lastName);
// 表达式体析构函数
~Person() => Console.WriteLine("Person对象被销毁");
}
- 更多实例
public class Product
{
public string Name { get; set; }
public decimal Price { get; set; }
public int Quantity { get; set; }
// 计算总价
public decimal TotalPrice => Price * Quantity;
// 判断是否有库存
public bool InStock => Quantity > 0;
// 价格是否合理
public bool IsExpensive => Price > 100;
// 获取商品信息摘要
public string Summary => $"{Name} - ¥{Price} {(InStock ? "有货" : "缺货")}";
}
public class MathHelper
{
// 数学计算方法
public static double CircleArea(double radius) => Math.PI * radius * radius;
public static bool IsEven(int number) => number % 2 == 0;
public static string NumberType(int num) => num > 0 ? "正数" : num < 0 ? "负数" : "零";
}
- 实例应用
// 创建对象并使用
var product = new Product
{
Name = "笔记本电脑",
Price = 5999,
Quantity = 5
};
Console.WriteLine(product.Summary); // 笔记本电脑 - ¥5999 有货
Console.WriteLine(product.TotalPrice); // 29995
Console.WriteLine(product.IsExpensive); // True
// 使用数学帮助类
Console.WriteLine(MathHelper.CircleArea(5)); // 78.54...
Console.WriteLine(MathHelper.IsEven(10)); // True
Console.WriteLine(MathHelper.NumberType(-5)); // 负数
C# 表达式体成员详解
作为初学者,表达式体语法确实需要一些时间来熟悉。让我通过多个例子来帮助你理解:
1. 只读属性(你代码中的用法)
// 传统写法
public int TemperatureF
{
get { return 32 + (int)(TemperatureC / 0.5556); }
}
// 表达式体写法(更简洁)
public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
2. 方法中的表达式体
public class Calculator
{
// 传统方法
public int Add(int a, int b)
{
return a + b;
}
// 表达式体方法
public int Add(int a, int b) => a + b;
public double Divide(double x, double y) => y != 0 ? x / y : 0;
}
3. 只读属性计算
public class Rectangle
{
public double Width { get; set; }
public double Height { get; set; }
// 计算面积
public double Area => Width * Height;
// 计算周长
public double Perimeter => 2 * (Width + Height);
// 判断是否为正方形
public bool IsSquare => Width == Height;
}
4. 构造函数和析构函数
public class Person
{
public string FirstName { get; }
public string LastName { get; }
// 表达式体构造函数
public Person(string firstName, string lastName) =>
(FirstName, LastName) = (firstName, lastName);
// 表达式体析构函数
~Person() => Console.WriteLine("Person对象被销毁");
}
5. 属性访问器
public class Student
{
private string _name;
public string Name
{
get => _name;
set => _name = value ?? throw new ArgumentNullException(nameof(value));
}
private int _age;
public int Age
{
get => _age;
set => _age = value >= 0 ? value : throw new ArgumentException("年龄不能为负数");
}
}
6. 更多实用例子
public class Product
{
public string Name { get; set; }
public decimal Price { get; set; }
public int Quantity { get; set; }
// 计算总价
public decimal TotalPrice => Price * Quantity;
// 判断是否有库存
public bool InStock => Quantity > 0;
// 价格是否合理
public bool IsExpensive => Price > 100;
// 获取商品信息摘要
public string Summary => $"{Name} - ¥{Price} {(InStock ? "有货" : "缺货")}";
}
public class MathHelper
{
// 数学计算方法
public static double CircleArea(double radius) => Math.PI * radius * radius;
public static bool IsEven(int number) => number % 2 == 0;
public static string NumberType(int num) => num > 0 ? "正数" : num < 0 ? "负数" : "零";
}
7. 使用示例
// 创建对象并使用
var product = new Product
{
Name = "笔记本电脑",
Price = 5999,
Quantity = 5
};
Console.WriteLine(product.Summary); // 笔记本电脑 - ¥5999 有货
Console.WriteLine(product.TotalPrice); // 29995
Console.WriteLine(product.IsExpensive); // True
// 使用数学帮助类
Console.WriteLine(MathHelper.CircleArea(5)); // 78.54...
Console.WriteLine(MathHelper.IsEven(10)); // True
Console.WriteLine(MathHelper.NumberType(-5)); // 负数
关键要点
-
语法:
成员 => 表达式 -
适用场景:
- 方法体只有一行返回语句
- 只读属性
- 简单的属性访问器
-
优点:
- 代码更简洁
- 可读性更强
- 减少大括号嵌套
-
限制:
- 不能包含复杂的逻辑块
- 不能使用多个语句
记住:表达式体主要是为了让简单的单行代码更简洁,对于复杂的逻辑还是应该使用传统的大括号语法。

浙公网安备 33010602011771号