当前位置: 首页 > news >正文

C#基础04-基础语法

零、文章目录

C#基础04-基础语法

1、数据类型

(1)值类型
  • 直接存储数据,分配在栈内存中,赋值时复制完整数据。
  • 简单类型
    • 整数:byte(0-255)、sbyte(-128-127)、shortushortint(默认)、uintlongulong
    • 浮点数:
      • float(单精度,后缀 F,如 3.14F
      • double(双精度,默认小数类型)
    • 高精度小数:decimal(财务计算,后缀 M,如 10.99M
    • 布尔型:bool(仅 true/false
    • 字符型:char(单个Unicode字符,如 'A'
  • 复合类型
    • 枚举(Enum):自定义常量集合,如 enum Days { Mon, Tue }
    • 结构体(Struct):轻量级数据封装(如坐标点),不可继承,适合小数据块。
(2)引用类型
  • 存储数据的内存地址,分配在堆内存中,赋值时复制引用而非数据本身。
  • 内置类型
    • 字符串(string):不可变字符序列(如 "Hello"),支持逐字字符串(@"C:\path")。
    • 对象(object):所有类型基类,可装箱值类型(如 object obj = 42;)。
    • 动态类型(dynamic):绕过编译时检查,运行时解析类型。
  • 自定义类型
    • 类(Class):支持继承、构造函数,如 class Person { }
    • 接口(Interface):定义契约,无实现(如 interface ILogger { void Log(); })。
    • 数组(Array):同类型元素集合(如 int[] arr = new int[5];)。
    • 委托(Delegate):方法引用(如 Action<int> print = Console.WriteLine;)。
️(3)特殊类型
  • 可空类型(Nullable)
    • 值类型扩展(如 int? num = null;),避免值类型无法为 null 的限制。
  • 指针类型(Pointer)
    • 仅用于unsafe上下文,直接操作内存(如 int* ptr;)。
(4)类型转换
  • 转换方式
    • 隐式转换:小范围转大范围(如 intlong)。
    • 显式转换:强制类型转换(如 (int)3.14)。
    • 方法转换:Parse()Convert.ToInt32() 等。
(5)类型选择

2、装箱与拆箱

(1)基本概念与原理
  • 定义
    • 装箱:将值类型(如 intstruct)转换为引用类型(如 object 或接口类型)。
int i = 123;
object o = i;  // 装箱操作
- 拆箱:将引用类型显式转换回原始值类型。  
int j = (int)o;  // 拆箱操作(需类型严格匹配)
- 本质:值类型存储在栈上,引用类型在托管堆分配内存。装箱时在堆中创建对象副本并返回其引用;拆箱时从堆中复制值回栈。
  • 内存操作流程
操作步骤
装箱1. 在堆分配内存(值类型大小 + 方法表指针 + SyncBlockIndex) 2. 复制值类型数据到堆 3. 返回对象引用地址
拆箱1. 检查对象是否为对应值类型的装箱实例 2. 获取堆中值类型字段地址 3. 复制值到栈上的变量
(2)性能影响与常见场景
  • 性能损耗根源
    • 每次装箱/拆箱均涉及堆内存分配和数据复制,尤其在循环或高频调用中显著降低效率。
    • 示例:4000万次装箱耗时约1.4秒,而泛型集合几乎无开销。
  • 典型触发场景
    • 值类型存入非泛型集合(如 ArrayList)时自动装箱:
ArrayList list = new ArrayList();
list.Add(42);  // int 被装箱为 object
- 传递给 `object` 类型参数的方法:  
void Process(object obj) { ... }
Process(10);  // 装箱发生 
- 值类型转换为接口类型(如 `ICloneable`)。
(3)优化策略
  • 优先使用泛型集合:用 List<T> 替代 ArrayList 避免装箱:
List<int> genericList = new List<int>();
genericList.Add(42);  // 无装箱 
  • 方法重载替代 object 参数:为值类型设计专用重载方法:
void Process(int value) { ... }   // 直接处理值类型 
void Process(object obj) { ... }   // 备用 
  • 谨慎调用继承方法
    • 调用重写的 ToString() 不触发装箱(编译器直接调用)。
    • 调用 GetType() 或未重写的基类方法(如 System.ValueType 方法)会强制装箱。
  • 避免接口转换装箱:值类型实现接口时,转换为接口类型将装箱:
ICloneable c = (ICloneable)a;  // 装箱发生 
(4)易错点与陷阱
  • 拆箱类型必须严格匹配
object o = 10;
long num = (long)o;  // 抛出 InvalidCastException 
int num = (int)o;    // 正确 
  • 装箱后修改不影响原始值:装箱创建的是副本,修改原值不影响装箱对象:
int a = 5;
object o = a;  // 装箱副本 
a = 10;
Console.WriteLine(o);  // 输出 5
  • 可变值类型(struct)的陷阱:已装箱的结构体无法直接修改字段,需拆箱→修改→重新装箱:
Point p = new Point(1, 1);
object o = p;
p.X = 2;             // 不影响 o 
((Point)o).X = 2;    // 编译错误:无法修改装箱副本 
(5)总结
关键点行动建议
避免非泛型集合使用 List<T>/Dictionary<T> 替代非泛型容器
警惕接口转换减少值类型向接口类型的隐式转换
方法设计为值类型提供重载方法
类型安全检查拆箱前用 isas 验证类型

3、变量

(1)定义与赋值
  • 声明语法
数据类型 变量名;          // 声明不初始化 
数据类型 变量名 =;     // 声明并初始化(推荐)
  • 示例:
int age;                // 声明整数变量 
string name = "Alice";  // 声明并初始化字符串变量 
double price = 9.99;    // 声明双精度浮点数
  • 多变量声明:可一次性声明同类型多个变量:
int a = 5, b = 10, c;  // c 未初始化 
(2)类型与内存管理
  • 值类型变量
    • 直接存储数据,内存分配在栈上
    • 包括整数 (int)、浮点数 (float)、布尔 (bool)、结构体 (struct) 等
    • 特点:赋值时复制完整数据副本。
  • 引用类型变量
    • 存储数据的内存地址,内存分配在堆上
    • 包括类 (class)、字符串 (string)、数组 (int[])、接口 (interface)
    • 特点:赋值时复制引用地址,多个变量可指向同一对象。
  • 关键区别:
// 值类型示例 
int x = 10;
int y = x;  // y 获得 x 的副本(修改 x 不影响 y)// 引用类型示例 
int[] arr1 = { 1, 2 };
int[] arr2 = arr1;     // arr2 指向 arr1 的地址 
arr2[0] = 99;         // arr1[0] 也变为 99
(3)作用域与生命周期
作用域类型定义位置访问范围示例
局部变量方法/代码块内部仅限所在代码块void Foo() { int local = 5; }
成员变量类内部(与方法同级)类内所有方法class Person { private int age; }
静态变量类内部 + static 修饰全局可访问(无需实例化)public static int Count;
全局变量方案静态类封装跨窗体/类访问public static class Global { public static string UserName; }
  • 最佳实践:
    • 避免滥用静态变量(常驻内存易导致性能问题)
    • 优先使用局部变量,减少命名冲突风险
(4)命名规范与规则
  • 强制规则:
    • 以字母/下划线开头,后续可包含字母、数字、下划线
    • 区分大小写(myVarMyVar
    • 禁止使用 C# 关键字(如 intclass
  • 行业惯例:
    • Camel 命名法(局部变量/参数):首单词小写,后续单词首字母大写 → userAgeitemList
    • Pascal 命名法(公共成员/类):所有单词首字母大写 → UserNameCalculateTotal()
    • 拒绝无意义命名(如 a1, tmp
(5)关键注意事项
  • 初始化要求:局部变量使用前必须显式赋值,否则编译错误
int num;
Console.WriteLine(num); // 错误:未赋值 
  • 常量声明(const):
    • 值在编译时确定,不可修改
    • 必须声明时初始化
const double PI = 3.14; // 正确 
const int MAX_SIZE;     // 错误:未初始化 
  • 字符串特性: string 为不可变引用类型,修改会创建新对象
string s1 = "Hello";
s1 += " World"; // 新建字符串对象,原对象待回收
(6)精选实例场景
// 用户输入转数值变量 
Console.Write("请输入年龄:");
string input = Console.ReadLine();
int age = int.Parse(input); // 字符串转整数 // 枚举类型变量 
enum Status { Running, Stopped }
Status current = Status.Running;// 可空值类型(允许 null)
int? score = null;  
if (score.HasValue) Console.WriteLine(score.Value);

4、深拷贝浅拷贝

(1)核心概念对比
特性浅拷贝深拷贝
定义仅复制对象的值类型成员和引用类型成员的地址引用(指向同一内存实例)递归复制对象的所有层级成员,包括引用类型成员的实际对象(创建全新实例)
影响范围修改副本的引用类型成员会影响原始对象(共享数据)副本与原始对象完全独立,互不影响
实现方法MemberwiseClone()Object类内置方法)反射、序列化、表达式树、手动实现
适用场景对象无嵌套引用类型或无需隔离引用数据对象含嵌套引用类型且需完全隔离数据
(2)浅拷贝实现
public class Person : ICloneable 
{public string Name;      // 值类型(字符串不可变)public Address Address; // 引用类型 public object Clone(){return this.MemberwiseClone(); // 调用基类浅拷贝方法 }
}public class Address 
{public string City;
}// 测试代码 
Person p1 = new Person { Name = "Alice", Address = new Address { City = "Beijing" } };
Person p2 = (Person)p1.Clone();
p2.Address.City = "Shanghai"; // 修改副本的地址 
Console.WriteLine(p1.Address.City); // 输出 "Shanghai"(原始对象被影响)
(3)深拷贝实现
  • 反射:解决循环引用需额外处理,如用字典缓存已拷贝对象避免无限递归。
public static T DeepCopyByReflection<T>(T obj)
{if (obj is string || obj.GetType().IsValueType) return obj;object retval = Activator.CreateInstance(obj.GetType());foreach (FieldInfo field in obj.GetType().GetFields()){object value = field.GetValue(obj);field.SetValue(retval, DeepCopyByReflection(value)); // 递归复制引用类型 }return (T)retval;
}
  • 序列化(推荐方式):序列化法支持复杂对象图,但需确保所有嵌套类可序列化(标记 [Serializable] 特性)。
// 二进制序列化(需标记 [Serializable])
public static T DeepCopyBySerialization<T>(T obj)
{using (MemoryStream ms = new MemoryStream()){BinaryFormatter formatter = new BinaryFormatter();formatter.Serialize(ms, obj);ms.Seek(0, SeekOrigin.Begin);return (T)formatter.Deserialize(ms);}
}// JSON 序列化(需引用 Newtonsoft.Json)
public static T DeepCopyByJson<T>(T obj)
{return JsonConvert.DeserializeObject<T>(JsonConvert.SerializeObject(obj));
}
  • 表达式树(高性能方案):通过动态生成表达式树编译为委托,实现高效深拷贝(适用于频繁拷贝场景)。
(3)典型场景分析
场景推荐拷贝方式原因
对象无嵌套引用类型浅拷贝效率最高(MemberwiseClone 是内存级复制)
嵌套引用类型需完全隔离序列化深拷贝自动处理复杂对象图,代码简洁
高频深拷贝且对象结构稳定表达式树编译后接近原生代码性能
需精细控制拷贝过程手动实现深拷贝对特定字段定制逻辑(如忽略某些属性)
(4)实践建议
  • 优先序列化法:使用 Newtonsoft.JsonSystem.Text.Json 实现深拷贝,兼顾安全性与可维护性。
  • 警惕循环引用:反射实现时需用字典记录已拷贝对象,避免栈溢出。
  • 性能权衡:浅拷贝性能最优,深拷贝中表达式树 > 反射 > 序列化(实测序列化比反射慢 10 倍以上)。
  • 不可变类型优化:若引用类型为不可变(如 string),浅拷贝即可满足隔离需求。

5、运算符

(1)分类与功能
类别运算符功能说明示例
算术运算符+ - * / % ++ --数值计算(含自增/减)int a = (10 + 3) * 2;
关系运算符== != > < >= <=值比较(返回boolif (age >= 18) {...}
逻辑运算符&& ` !`
位运算符& ` ^` `~` `<<` `>>`二进制位操作(异或^:相同为0,不同为1)
赋值运算符= += -= *= /= &= `=`赋值与复合赋值
特殊运算符?: is as sizeof typeof ??条件/类型检查/空值处理string s = input ?? "default";
  • + 可重载用于字符串拼接(如 "Hello" + name
  • 异或运算 ^ 常用于加密校验(如 a ^ b ^ a = b
  • 条件运算符 ?: 是唯一的三元运算符:condition ? val1 : val2
(2)优先级
  • 顶级:()(括号) .(成员访问) ++(前缀自增) --(前缀自减) ! ~
    → 优先级最高,括号强制改变顺序
int r = (a + b) * c; // 括号优先
  • 算术运算:* / %+ -
    → 乘除优先于加减
double v = 5 + 3 * 2; // 结果=11(非16)
  • 位移运算:<< >>
    → 处理二进制移位(如 0x01 << 2 = 0x04
  • 关系比较:> < >= <=== !=
    → 大小比较优先于相等性判断
  • 逻辑运算:&^\|&&\|\|
    → 短路逻辑&&/\|\|效率高于位逻辑
  • 赋值运算:=及复合赋值(如 +=
    → 优先级最低,最后执行
  • 后缀运算:++ --(后缀形式)
int i = 5;
int j = i++; // j=5,i自增到6
  • 优先级口诀:括号 > 算数 > 移位 > 比较 > 逻辑 > 赋值
️(3)关键注意事项
  • 类型兼容性: 算术运算需操作数类型相同(如 int + double 需显式转换)
double r = 5 + 2.0; // 合法(int隐式转double)
  • 短路逻辑优化: && 左侧为false时跳过右侧计算,\|\| 左侧为true时同理
  • 空值处理: 空合并运算符 ?? 避免NullReferenceException
string name = input ?? "Unknown"; // input为null时返回"Unknown"
  • 运算符重载:支持自定义类型重载 +== 等(需public static方法)
(4)调试与最佳实践
  • 复杂表达式拆分:
// 难读写法 
bool valid = (a > b) && (c != d) || (e == f); 
// 优化后 
bool cond1 = a > b;
bool cond2 = c != d;
bool cond3 = e == f;
bool valid = cond1 && cond2 || cond3;
  • 避免优先级混淆:多用括号明确意图(如 (a \| b) && c 区别于 a \| (b && c)

6、相等Equals

(1)Equals 方法的默认行为
  • 引用类型
    • 默认比较对象的引用地址(即是否为同一实例)。
    • 示例:
var obj1 = new object();
var obj2 = new object();
Console.WriteLine(obj1.Equals(obj2)); // False(不同实例)
  • 值类型
    • 默认通过 ValueType.Equals 比较所有字段的值是否相等(使用反射,性能较低)。
    • 建议重写以提升效率。
(2)重写 Equals 的规范步骤
  • 检查 null 和类型一致性
public override bool Equals(object obj)
{if (obj == null) return false;if (ReferenceEquals(this, obj)) return true; // 同一实例if (obj.GetType() != this.GetType()) return false; // 类型不同return Equals((MyClass)obj); // 调用强类型方法
}
  • 实现 IEquatable<T> 接口(避免装箱)
public bool Equals(MyClass other)
{// 逐个比较关键字段return this.Field1 == other.Field1 && this.Field2.Equals(other.Field2);
}
  • 重写 GetHashCode():必须保证若两对象 Equals 返回 true,则其哈希码必须相同
public override int GetHashCode()
{return (Field1, Field2).GetHashCode();
}
  • 重载 ==!= 运算符
public static bool operator ==(MyClass a, MyClass b) => Equals(a, b);
public static bool operator !=(MyClass a, MyClass b) => !Equals(a, b);
(3)其他相等性判断方法
方法适用场景示例
ReferenceEquals(a, b)强制比较引用地址(值类型永远返回 falseReferenceEquals("a", "a")false
== 运算符默认行为同 Equals,但可被重载(如 string 比较值)"a" == "a"true
  • 特殊类型注意:stringEquals== 均比较内容而非引用。
  • 忽略大小写比较字符串:
"HELLO".Equals("hello", StringComparison.OrdinalIgnoreCase); // true
(4)必须遵守的相等性原则
  • 自反性:x.Equals(x)true
  • 对称性:若 x.Equals(y)true,则 y.Equals(x) 必须为 true
  • 传递性:若 x.Equals(y)y.Equals(z)true,则 x.Equals(z) 必须为 true
  • 一致性:多次调用结果不变。
(5)常见误区
  • 值类型使用 ReferenceEquals:因装箱导致结果恒为 false
  • 未同步重写 GetHashCode:导致哈希集合(如 Dictionary)行为异常。
  • 混淆 ==Equals:引用类型未重载时二者等效,但值类型 == 需显式重载。
(6)最佳实践
  • 值类型:务必重写 EqualsGetHashCode,避免反射开销。
  • 引用类型:若需值语义比较,完整实现 IEquatable<T> + 运算符重载。
  • 字符串比较:明确指定 StringComparison 参数以避免区域性差异。

7、关键字

(1)基础声明与类型定义
关键字功能说明示例
class定义引用类型,封装数据和行为class Person { public string Name; }
struct定义值类型,适用于轻量数据结构(≤16字节)struct Point { public int X, Y; }
enum声明枚举类型(固定值集合)enum Status { Running, Stopped }
delegate定义方法签名,用于事件和回调delegate void LogHandler(string message);
interface定义契约(无实现),支持多继承interface IDrawable { void Draw(); }
(2)流程控制与逻辑处理
  • 循环与分支
    • if/else:条件判断
if (age > 18) Console.WriteLine("Adult");
- `switch`/`case`:多路分支  
switch (status) { case Status.Running: break; }
- `for`/`foreach`:迭代集合  
foreach (var item in list) { ... }
- `break`/`continue`:循环控制  * `break` 终止当前循环,`continue` 跳过本次迭代
  • 异常处理
    • try/catch/finally:捕获异常并清理资源
try { ... } catch (Exception ex) { ... } finally { ... }
- `throw`:主动抛出异常
(3)面向对象核心特性
关键字用途示例规则
virtual声明可重写方法public virtual void Calculate() { ... }派生类用 override 重写
override重写基类虚方法public override void Calculate() { ... }方法签名必须一致
abstract定义抽象成员(无实现),强制派生类实现public abstract void Render();只能在抽象类中使用
sealed禁止类被继承或方法被重写sealed class AdminUser : User { }常与 override 联用
base调用基类构造方法或成员public Child() : base() { }必须在构造函数首行
this引用当前实例成员this.name = name;区分同名局部变量
(4)类型操作与安全
  • 类型转换
    • as:安全类型转换(失败返回 null
Shape s = circle as Shape;
- `is`:类型检查  
if (obj is string) { ... }
- `typeof`:获取类型元数据  
Type t = typeof(int);
  • 空值处理
    • null:空引用
    • ??:空合并运算符
string name = input ?? "Unknown";
  • 类型约束
    • where:泛型类型约束
class Repository<T> where T : IDisposable { }
(5)特殊功能关键字
关键字用途场景示例注意
using引入命名空间或自动释放资源using (var file = new StreamReader(...)) { ... }实现 IDisposable 的对象
unsafe启用指针操作(需项目配置)unsafe { int* p = &num; }仅限信任环境
fixed固定变量内存地址(防GC回收)fixed (int* ptr = arr) { ... }unsafe 块内使用
volatile确保多线程下字段可见性private volatile bool _isRunning;避免编译器优化
const定义编译时常量const double PI = 3.14;必须初始化且不可修改
readonly定义运行时常量(构造函数内可赋值)public readonly string Id = Guid.NewGuid().ToString();const 更灵活
(6)上下文关键字
  • var:隐式类型推断(编译时确定类型)
var list = new List<int>();  // 等价 List<int>
  • value:属性/索引器的隐式参数
public string Name { set { _name = value; } }
  • yield:迭代器生成元素
IEnumerable<int> GetNumbers() { yield return 1; }
  • async/await:异步编程模型
async Task LoadData() { await httpClient.GetAsync(...); }
(7)关键对比速查表
场景推荐关键字替代方案选择依据
方法返回值void-无返回值时必用
跨方法返回多个值out/ref元组/自定义对象简单场景用 out
,需双向修改用 ref
常量定义constreadonly编译时确定用 const
,运行时用 readonly
禁止继承sealed私有构造函数需完全封闭类时
异步操作async/await回调/ThreadPool简化异步代码流

8、注释

(1)基础类型与语法
  • 单行注释 (//) :解释单行代码或临时禁用代码
int age = 30; // 用户年龄(直接说明变量含义)
// Console.WriteLine("调试信息"); // 临时注销代码 
  • 多行注释 (/* ... */) :注释代码块或详细说明复杂逻辑
/* 
此方法计算商品折扣价:
- 会员折扣:8折
- 非会员:无折扣
*/
double ApplyDiscount(double price, bool isMember) {...}
  • XML文档注释 (///) :生成API文档,兼容IDE智能提示
/// <summary>
/// 计算两个数的和
/// </summary>
/// <param name="a">第一个整数</param>
/// <param name="b">第二个整数</param>
/// <returns>两数之和</returns>
int Add(int a, int b) => a + b;
(2)核心作用与场景
  • 代码解释
    • 说明复杂算法意图(如排序逻辑)
    • 标注关键参数含义(避免歧义)
    • 提升代码可维护性
  • 调试辅助
    • 临时禁用代码段(/* ... */包裹)
    • 标记待优化区域(// TODO: 重构此方法
  • 文档生成
    • XML注释可通过工具(如Sandcastle)生成HTML/CHM文档
(3)高级技巧与最佳实践
  • 条件编译注释:根据编译条件启用/禁用代码:
#if DEBUG 
Console.WriteLine("调试模式输出"); 
#endif
  • 注释规范建议
    • 简洁性:避免冗余(如i++; // i自增
    • 实时性:代码修改后同步更新注释
    • 一致性:团队统一注释风格(如所有公共方法用XML注释)
  • VS智能应用
    • 输入///自动生成XML模板(自动填充<param>等标签)
    • 折叠注释区域:#region 算法说明 ... #endregion
(4)注意事项
  • 嵌套问题:多行注释不可嵌套(/* /* 错误示例 */ */
  • 位置规范:
    • 类/方法声明前用XML注释
    • 关键逻辑旁用单行注释
  • 特殊字符:XML注释中需转义<&lt;
(5)综合示例
/// <summary>
/// 用户账户管理类 
/// </summary>
public class AccountManager
{/* 账户状态定义:0: 正常  1: 冻结  2: 注销*/private int _status; /// <summary>/// 验证登录凭证 /// </summary>/// <param name="username">用户名(长度3-20字符)</param>/// <param name="password">密码(MD5加密)</param>/// <returns>验证成功返回true</returns>public bool Login(string username, string password){// 检查用户名格式 if (username.Length < 3) // 长度不足return false;// 密码验证逻辑(实际需对接数据库)return true;}
}
http://www.dtcms.com/a/432268.html

相关文章:

  • 网站建设期间工作软文营销方法有哪些
  • 网站登陆注册怎么做宁波seo整站优化软件
  • 网站在互联网营销中的作用互联网相关网站
  • Easyx使用(中篇)
  • 省品牌建设联合会网站平面设计图片创意手绘
  • 山西教育学会网站建设网站搭建推广优化
  • 移动端开发平台海南百度推广seo
  • 网站建设与维护的国家定价标准淄博专业网站建设公司
  • 网站设计用什么字体网站商城系统建设方案
  • 广东省农业农村厅彭彬湛江网站优化快速排名
  • 亚马逊品牌注册网站建设建设银行怎么从网站上改手机号码
  • 上海建站模板源码个人简历模板免费下
  • 现在c 做网站用什么软件vps安装wordpress
  • 中国移动深圳有限公司门户网站seo怎么做优化排名
  • 外国购物网站设计风格wordpress头部导航栏代码
  • 互联网金融p2p网站建设模板万装网装修平台
  • 做外单都有什么网站网站建公司简介
  • 正规网站制作全包企业网站如何去做优化
  • 太仓网站制作网站建设网站首页栏目设置
  • aspnet网站开发教程数据库常州快速建站模板
  • 【算法竞赛学习笔记】基础算法篇:递归再探
  • 杭州门户网站建设工信部网站备案怎么查询
  • 多线程环境下虚函数性能评估与优化指南
  • 高端网站设计欣赏视频门户网站建设服务器
  • 实用的LoRaWAN 应用层协议规范
  • 阿里云 建网站攻略做网站一屏一屏的
  • 沈阳营销型网站开发网站的流量怎么赚钱
  • 网站开发属于什么费用wordpress 文章循环
  • 音视频编解码全流程之用Extractor后Decodec
  • 03.动画眼睛跟随鼠标光标 | JavaScript 鼠标移动事件