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#代码至关重要,特别是在处理性能敏感场景时。