C# 中比较实用的关键字,基础高频面试题!
前言
在C#编程中关键字是构建逻辑和实现功能的基石,它承载着编程语言的语法规则和编程智慧。熟练掌握这些基础高频关键字对提升编程能力和面试表现至关重要,它们是日常开发和解决复杂问题的关键。
DotNetGuide
全面的C#/.NET/.NET Core学习、工作、面试指南,记录、收集和总结C#/.NET/.NET Core基础知识、学习路线、开发实战、编程技巧练习、学习视频、文章、书籍、项目框架、社区组织、开发必备工具、技术前沿周刊、常见面试题、面试须知、简历模板、人才招聘、以及自己在学习和工作中的一些微薄见解。

C#访问修饰符
访问修饰符的作用
访问修饰符是用于指定成员或类型的声明可访问性的关键字。
四种常见的访问修饰符
- public(公共的)
- protected(受保护的)
- internal(内部的)
- private(私有的)
访问修饰符的六种组合及其可访问性级别
- public 访问不受限制
- protected 访问限于包含类或派生自包含类的类型
- internal 访问限于当前程序集
- private 访问限于包含类
- protected internal 访问限于当前程序集或派生自包含类的类型访问
- private protected 访问限于包含类或当前程序集中包含类的派生类的类型访问
//包含类
publicclassBaseClass
{
privateprotectedint myValue = 0;
}
//当前程序集中包含类的派生类
publicclassDerivedClass1 : BaseClass
{
void Access()
{
var baseObject = new BaseClass();
myValue = 5;
}
}
C#类和结构默认访问修饰符
Internal
C#适用于类和结构访问修饰符有哪些
public 或 internal
类成员和结构成员的默认访问修饰符为
private
结构成员(包括嵌套的类和结构)可以声明为
public、internal 或 private 注意:结构成员无法声明为 protected、protected internal 或 private protected,因为结构不支持继承。
类成员(包括嵌套的类和结构)可以声明为
public、protected internal、protected、internal、private protected 或 private
readonly与const区别?
readonly关键字(运行时常量):字段可以在声明或构造函数中初始化,常作为运行时常量使用。
const关键字(编译时常量):字段只能在该字段的声明时初始化,常作为编译时常量使用过。
virtual作用?
详情阅读:https://docs.microsoft.com/zh-cn/dotnet/csharp/language-reference/keywords/virtual
virtual关键字用于修改方法、属性、索引器或事件声明,并使它们可以在派生类中被重写(使用override关键字对虚方法重写)。 如下是虚方法声明和重写虚方法的示例:
// 基类虚方法声明
class BaseClass
{
public virtual void Method1()
{
Console.WriteLine("Base - Method1");
}
public virtual void Method2()
{
Console.WriteLine("Base - Method2");
}
}
class DerivedClass : BaseClass
{
// 重写基类中的虚方法
public override void Method1()
{
Console.WriteLine("Derived - Method1");
}
public new void Method2()
{
Console.WriteLine("Derived - Method2");
}
}
override作用?
扩展或修改继承的方法、属性、索引器或事件的抽象或虚拟实现需要 override 修饰符。
static作用?
详情阅读:https://docs.microsoft.com/zh-cn/dotnet/csharp/language-reference/keywords/static
使用 static 修饰符可声明属于类型本身而不是属于特定对象的静态成员。 static 修饰符可用于声明 static 类。 在类、接口和结构中,可以将 static 修饰符添加到字段、方法、属性、运算符、事件和构造函数。 static 修饰符不能用于索引器或终结器。
静态类与非静态类的区别?
- 静态类无法实例化(换句话说,无法使用 new 运算符创建类类型的变量。 由于不存在任何实例变量,因此可以使用类名本身访问静态类的成员)。
- 静态构造函数只调用一次,在程序所驻留的应用程序域的生存期内,静态类会保留在内存中(即使用Static修饰的类,应用一旦启用静态类就会保留在内存中)。
- 静态类只包含静态成员
- 不能包含实例构造函数。
- 静态类会进行密封,因此不能继承。 它们不能继承自任何类(除了 Object)。 静态类不能包含实例构造函数。 但是,它们可以包含静态构造函数。
静态成员和非静态成员的区别?
成员主要指的是:字段、方法、属性、运算符、事件和构造函数等。
- 静态成员用static修饰符,非静态成员不需要。
- 静态成员属于类所有,非静态成员属于类的实例化对象所有。
- 静态方法里不能使用非静态成员,非静态方法可以使用静态成员。
- 每创建一个类的实例,都会在内存中为非静态成员新分配一块新的存储。
- 静态成员无论类创建多少个实例,在内存中只占同一块区域。
静态方法的使用场合
- 静态方法最适合工具类中方法的定义。
- 静态变量适合全局变量的定义。
静态方法和非静态方法区别(优/缺点)?
优点:
- 属于类级别的,不需要创建对象就可以直接使用。
- 全局唯一,内存中唯一,静态变量可以唯一标识某些状态。
- 在类加载时候初始化,常驻在内存中,调用快捷方便。
缺点:
- 静态方法不能调用非静态的方法和变量。(非静态方法可以任意的调用静态方法/变量)
- 不可以使用 this 引用 static 方法或属性访问器。
sealed 关键字有什么作用?
sealed 关键字用于修饰类、方法或属性,表示该类或成员不可被继承或重写。如果一个类被声明为 sealed,其他类不能继承该类;如果一个方法或属性被声明为 sealed,其他类不能重写该方法或属性。
this 关键字有什么作用?
this 关键字表示当前对象的引用,可以用于访问当前对象的成员。它可以用来区分局部变量和实例变量、在构造函数中调用其他构造函数、传递当前对象给其他方法等。
base 关键字有什么作用?
base 关键字表示基类的引用,可以用于访问基类的成员。它可以用来在子类中调用基类的构造函数、调用基类的方法或属性等。
sizeof 关键字有什么作用?
sizeof 运算符返回给定类型的变量所占用的字节数。 sizeof 运算符的参数必须是一个非托管类型的名称,或是一个限定为非托管类型的类型参数。
lock 关键字有什么作用?
lock 关键字用于在多线程环境下对共享资源进行互斥访问。使用 lock 关键字可以将代码块标记为临界区,使得只有一个线程能够进入临界区执行代码。
async 和 await 关键字有什么作用?
async 和 await 关键字用于异步编程。通过使用 async 标记方法和 await 等待异步操作完成,可以实现在异步任务执行过程中不阻塞主线程。
delegate 关键字有什么作用?
delegate 关键字用于声明委托类型,即代表一个或多个方法的对象。使用 delegate 可以实现事件和回调机制,简化方法的调用和管理。
using关键字的作用
- using指令为命名空间创建别名,或导入在其他命名空间中定义的类型
- using 语句定义一个范围,在此范围的末尾将释放对象资源,实现了IDisposiable的类在using中创建,using结束后会自定调用该对象的Dispose方法,释放资源。
C# 中的 in 关键字有什么作用?
in 关键字用于参数传递时,将参数按只读引用传递。使用 in 关键字可以提高性能,避免不必要的参数复制。
在 C# 中,in 关键字用于将参数标记为输入参数。它告诉编译器在方法调用过程中不会修改该参数的值,并且可以通过引用传递避免对参数进行复制。这对于大型结构或对象参数非常有用,因为直接引用参数可以提高性能和内存效率。
class Program
{
static void Main(string[] args)
{
int x = 5;
MultiplyByTwo(in x);
Console.WriteLine(x); // 输出 5
}
static void MultiplyByTwo(in int number)
{
// 无法修改 in 参数的值
// number *= 2; // 编译错误
// 仅能读取 in 参数的值
Console.WriteLine(number * 2); // 输出 10
}
}
C# 中的 ref 关键字有什么作用?
- 参数在使用 ref 关键字进行引用传递时,必须在方法调用之前对其进行初始化。
- ref 关键字既可以在进入方法之前初始化参数的值,也可以在方法内部对参数进行修改。
- ref 参数在进入方法时保持原始值,并在方法结束后将值带回到调用处。
C# 中的 out 关键字有什么作用?
- 参数在使用 out 关键字进行引用传递时,不需要在方法调用之前进行初始化。
- out 关键字通常用于表示方法返回多个值的情况,或者用于修改方法外部的变量。
- out 参数必须在方法内部进行初始化,并确保在方法结束前完成赋值操作。方法内部没有为 out 参数赋值的情况下,方法调用将会导致编译错误。
C#中参数传递 ref与out 的区别?
ref 指定此参数由引用传递,指定的参数在函数调用时必须先初始化(有进有出)。
out 指定此参数由引用传递,指定的参数在进入函数时会清空参数值,因此该参数必须在调用函数内部进行初始化赋值操作(无进有出)。
总结:
- ref 和 out 都用于引用传递参数。
- ref 参数在方法调用前必须被初始化,而 out 参数不需要。
- ref 参数可以保留原始值并在方法内部进行修改,而 out 参数必须在方法内部进行初始化赋值。
不能将 in、ref 和 out 关键字用于以下几种方法:
- 异步方法,通过使用 async 修饰符定义。
- 迭代器方法,包括 yield return 或 yield break 语句。
- 扩展方法的第一个参数不能有 in 修饰符,除非该参数是结构。
- 扩展方法的第一个参数,其中该参数是泛型类型(即使该类型被约束为结构)
as和is的区别
- is 只是做类型兼容判断,并不执行真正的类型转换。返回true或false,不会返回null,对象为null也会返回false。
- as运算符将表达式结果显式转换为给定的引用类型或可以为null值的类型。 如果无法进行转换,则as运算符返回 null。
总结:as模式的效率要比is模式的高,因为借助is进行类型转换的化,需要执行两次类型兼容检查。而as只需要做一次类型兼容,一次null检查,null检查要比类型兼容检查快。
is 运算符
is 运算符用于检查对象是否是某个特定类型,或者是否可以转换为该类型。它返回一个布尔值 (true 或 false)。
string title = "Hello DotNetGuide";
if (title is string)
{
Console.WriteLine("是 string 类型");
}
else
{
Console.WriteLine("不是 string 类型");
}
if (title is not null)
{
Console.WriteLine("不为 null");
}
else
{
Console.WriteLine("为 null");
}
模式匹配:C# 7.0 引入了模式匹配,允许在 is 表达式中进行类型检查和转换:
object obj = "追逐时光者";
if (obj is string str)
{
Console.WriteLine($" {str}");
}
else
{
Console.WriteLine("不是指定类型");
}
列表模式:从 C# 11 开始,可以使用列表模式来匹配列表或数组的元素。以下代码检查数组中处于预期位置的整数值:
int[] empty = [];
int[] one = [1];
int[] odd = [1, 3, 5];
int[] even = [2, 4, 6];
int[] fib = [1, 1, 2, 3, 5];
Console.WriteLine(odd is [1, _, 2, ..]); // false
Console.WriteLine(fib is [1, _, 2, ..]); // true
Console.WriteLine(fib is [_, 1, 2, 3, ..]); // true
Console.WriteLine(fib is [.., 1, 2, 3, _ ]); // true
Console.WriteLine(even is [2, _, 6]); // true
Console.WriteLine(even is [2, .., 6]); // true
Console.WriteLine(odd is [.., 3, 5]); // true
Console.WriteLine(even is [.., 3, 5]); // false
Console.WriteLine(fib is [.., 3, 5]); // true
as 运算符
as 运算符尝试将对象转换为特定类型,如果转换失败,则返回 null 而不是抛出异常。它通常用于在不需要显式检查对象是否为特定类型的情况下进行安全的类型转换。
object title = "Hello DotNetGuide";
string str = title as string;
if (str != null)
{
Console.WriteLine("是 string 类型: " + str);
}
else
{
Console.WriteLine("不是 string 类型");
}
int? num = title as int?;
if (num.HasValue)
{
Console.WriteLine("是 int 类型: " + num.Value);
}
else
{
Console.WriteLine("不是 int 类型");
}
null是什么类型?
null 关键字是表示不引用任何对象的空引用的文字值。 null是引用类型变量的默认值。 普通值类型不能为 null,可为空的值类型除外。
new关键字的作用?
- 运算符:创建类型的新实例
- 修饰符:可以显式隐藏从基类继承的成员。
- 泛型约束:泛型约束定义,约束可使用的泛型类型。
return、continue、break的区别?
return:
结束整个方法,return关键字并不是专门用于跳出循环的,return的功能是结束一个方法。 一旦在循环体内执行到一个return语句,return语句将会结束该方法,循环自然也随之结束。与continue和break不同的是,return直接结束整个方法,不管这个return处于多少层循环之内。
continue:
结束本次循环,然后持续进行下一次循环。
break:
break用于完全结束一个循环,跳出循环体。不管是哪种循环,一旦在循环体中遇到break,系统将完全结束循环,开始执行循环之后的代码。
yield
yield关键字在C#中简化了数据迭代的方式,实现了按需生成数据,自动维护迭代状态,减少了内存占用,并允许在迭代时执行复杂逻辑。
咱们来看看传统迭代方式和yield关键字迭代方式对比,是否如传说中的代码实现起来更简洁和高效:
/// <summary>
/// 传统迭代方式和yield关键字迭代方式对比
/// </summary>
public static void IteratorComparisonRun()
{
Console.WriteLine("迭代器方法使用yield关键字:");
foreach (var number in GetNumbersWithYield())
{
Console.WriteLine(number);
}
Console.WriteLine("传统迭代方法返回一个List<int>");
var numbers = GetNumbersWithoutYield();
foreach (var number in numbers)
{
Console.WriteLine(number);
}
}
/// <summary>
/// 迭代器方法使用yield关键字
/// </summary>
/// <returns></returns>
public static IEnumerable<int> GetNumbersWithYield()
{
for (int i = 0; i < 6; i++)
{
yield return i;
}
}
/// <summary>
/// 传统迭代方法返回一个List<int>
/// </summary>
/// <returns></returns>
public static List<int> GetNumbersWithoutYield()
{
var numbers = new List<int>();
for (int i = 0; i < 6; i++)
{
numbers.Add(i);
}
return numbers;
}

什么情况不能使用yield关键字
- 带有 in、ref 或 out 参数的方法。
- Lambda 表达式和匿名方法。
- 在 C# 13 之前,yield 在具有 unsafe 块的任何方法中都无效。从 C# 13 开始,可以在包含 unsafe 块的方法中使用 yield,但不能在 unsafe 块中使用。
- 不能在catch和finally块中使用yield return和yield break。
- 不能在具有catch块的try块中使用yield return和yield break。
- 可以在只有finally块的try块中使用yield return和yield break。
params
params适用于参数个数动态变化的场景,例如日志、数学计算或格式化输出等,减少冗余代码,增强方法通用性。
在 C# 13 之前:
params 仅支持一维数组(如params int[] list、params object[] list)。调用方法时需显式传递数组或数组元素类型的参数的逗号分隔列表。
在 C# 13 中:
params 修饰符并不局限于数组类型。 现在可以将 params 用于任何已识别的集合类型,包括 System.Span<T>、System.ReadOnlySpan<T>,以及那些实现 System.Collections.Generic.IEnumerable<T> 并具有 Add 方法的类型。 除了具体类型外,还可以使用接口 System.Collections.Generic.IEnumerable<T>、System.Collections.Generic.IReadOnlyCollection<T>、System.Collections.Generic.IReadOnlyList<T>、System.Collections.Generic.ICollection<T>和 System.Collections.Generic.IList<T>。
注意事项
在方法声明中的 params 关键字之后不允许有任何其他参数,并且在方法声明中只允许有一个 params 关键字。
goto跳转语句
- goto 语句由关键字 goto 后跟一个标签名称组成,通过标签名称指定跳转的位置。
- 可以在方法的任何地方放置标签,并且可以多次使用相同的标签。

/// <summary>
/// 使用goto进行代码重试示例
/// </summary>
public static void GotoRetryUseExample()
{
int retryCount = 0;
for (int i = 0; i < 10; i++)
{
retryLogic:
try
{
//模拟可能出错的操作
Random random = new Random();
int result = random.Next(0, 2);
if (result == 0)
{
throw new Exception("Error occurred");
}
Console.WriteLine("Operation successful on attempt: " + retryCount);
}
catch (Exception ex)
{
retryCount++;
if (retryCount < 3)
{
Console.WriteLine("Error occurred, retrying...");
goto retryLogic; //跳转到重试逻辑
}
else
{
Console.WriteLine("Max retry limit reached.");
return;
}
}
}
}
参考文章
- https://docs.microsoft.com/zh-cn/dotnet/csharp/language-reference/keywords/access-modifiers
- https://learn.microsoft.com/zh-cn/dotnet/csharp/language-reference/keywords
C# 中比较实用的关键字,基础高频面试题!的更多相关文章
- 2020年Java基础高频面试题汇总(1.4W字详细解析,你能遇到的都在这了)
1. Java语言有哪些特点 (1)简单易学.有丰富的类库 (2)面向对象(Java最重要的特性,让程序耦合度更低,内聚性更高) (3)与平台无关性(JVM是Java跨平台使用的根本) (4)可靠安全 ...
- 2020年Java基础高频面试题汇总(1.4W字详细解析)
1. Java语言有哪些特点 (1)简单易学.有丰富的类库 (2)面向对象(Java最重要的特性,让程序耦合度更低,内聚性更高) (3)与平台无关性(JVM是Java跨平台使用的根本) (4)可靠安全 ...
- 我在阿里这仨月 前端开发流程 前端进阶的思考 延伸学习的方式很简单:google 一个关键词你能看到十几篇优秀的博文,再这些博文中寻找新的关键字,直到整个大知识点得到突破
我在阿里这仨月 Alibaba 试用期是三个月,转眼三个月过去了,也到了转正述职的时间.回想这三个月做过的事情,很多很杂,但还是有重点. 本文谈一谈工作中遇到的各种场景,需要用到的一些前端知识,以及我 ...
- Java中this、static关键字的内存图解
Java中的关键字有很多,abstract default goto* null switch boolean do if package nchronzed break dou ...
- nginx中root与alias关键字的区别
前言 近段时间秋招上岸了,于是每天疯狂补各种分布式基础,每天都在痛苦与快乐中度过. 在学习 nginx 的时候,遇到配置上的问题:root 与 alias 的区别,卡了大概三个小时,记录下来警醒自己不 ...
- STM32中遇到的一些关键字
3.在STM32编程中遇到的一些关键字 STM32是基于RAM的架构,学习它可以是嵌入式的一个基础部分.因此对于一些关键字也必须了解,在STM32学习过程中,遇到过如下变量,对其有疑问 关键字 功能 ...
- Web 开发中很实用的10个效果【附源码下载】
在工作中,我们可能会用到各种交互效果.而这些效果在平常翻看文章的时候碰到很多,但是一时半会又想不起来在哪,所以养成知识整理的习惯是很有必要的.这篇文章给大家推荐10个在 Web 开发中很有用的效果,记 ...
- [转载]C#中as和is关键字的用法
这篇文章主要介绍了C#中as和is关键字的用法的相关资料,需要的朋友可以参考下. 原文链接:http://www.jb51.net/article/80944.htm#comments 在程序中,进 ...
- 微信开发中网页授权access_token与基础支持的access_token异同
问题1:网页授权access_token与分享的jssdk中的access_token一样吗? 答:不一样.网页授权access_token 是一次性的,而基础支持的access_token的是有时间 ...
- 网站开发中很实用的 HTML5 & jQuery 插件
这篇文章挑选了15款在网站开发中很实用的 HTML5 & jQuery 插件,如果你正在寻找能优化网站,使其更具创造力和视觉冲击,那么本文正是你需要的.这些优秀的 jQuery 插件能为你的网 ...
随机推荐
- Windows7下关闭和打开IPV6隧道
IPv6隧道是将IPv6报文封装在IPv4报文中,让IPv6数据包穿过IPv4网络进行通信.对于采用隧道技术的设备来说,在隧道的入口处,将IPv6的数据报封装进IPv4,IPv4报文的源地址和目的地址 ...
- 长连接网关技术专题(六):石墨文档单机50万WebSocket长连接架构实践
本文由石墨文档技术杜旻翔分享,原题"石墨文档 Websocket 百万长连接技术实践",有修订. 1.引言 在石墨文档的部分业务中,例如文档分享.评论.幻灯片演示和文档表格跟随等场 ...
- JMeter JSR223 Sampler 教程:性能测试的魔法棒
JMeter JSR223 Sampler 教程:性能测试的魔法棒 宝子们,今天咱要深入探索 JMeter 里超厉害的 JSR223 Sampler,它就像是一把万能钥匙,能打开性能测试的各种奇妙大门 ...
- 题解:AT_abc386_d [ABC386D] Diagonal Separation
分析题面,发现题目求的是是否存在一个白点被 \((1, 1)\) 和任意一个黑点围成的矩形内. 先将所有黑点按 \(x\) 坐标排序. 枚举所有的白点. 找到所有横坐标不比该白点横坐标小的所有黑点的纵 ...
- WPF 获取拖拽网页图片链接
在浏览器里拖拽一个元素,我只获取图片链接 private void Grid_PreviewDragOver(object sender, DragEventArgs e) { e.Effects = ...
- weixueyuan-Nginx Web服务4
https://www.weixueyuan.net/nginx/web/ Nginx静态资源服务器搭建 HTML 是一种标记语言,提供 HTML 文件读取是静态服务器最基本的功能,静态服务器的配置样 ...
- Docker与联合文件系统
1. 联合文件系统 概念 UnionFS(联合文件系统)是一种分层,轻量级并且高性能的文件系统,它支持对文件系统的修改作为一次次的提交来一层一层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下(u ...
- 0511-FileWrite字符输出流和JDK7中try..finally新的特性
package A10_IOStream; import java.io.*; /* java.io.Writer:字符输出流,是所有字符数出流的最顶层抽象父类 共性方法 void write(int ...
- 在SOUI中使用GetAttribute获取XML中配置的属性
SOUI的界面布局使用XML来布局,在XML配置的属性值会通过SObject::SetAttribute(name, value)的方式交给SObject处理. SWindow是SOUI的界面元素对象 ...
- 2024大湾区网络安全大会,AOne来了!
近日,2024大湾区网络安全大会暨第二十六期花城院士科技会议在广州启幕.学者专家.高校院长.政府相关负责人及行业大咖齐聚一堂,围绕网络安全的前沿话题与挑战展开深入交流与探讨.天翼云科技有限公司网络安全 ...