每天早上醒来,看见你和阳光都在,那就是我想要的未来。 --zhu
28、C#可否对内存直接操作
C#在unsafe模式下可以使用指针对内存进行操作,但在托管模式下不可用使用指针,C#.NET默认不允许带指针,需要设置,选择项目右键->属性->选择生成->“允许不安全代码”打勾->保存。
29、什么是强类型,什么是弱类型?哪种更好
强类型定义:强类型语言要求变量必须声明其类型,并且在赋值或操作过程中,类型必须明确且一致。如果类型不匹配,编译器会在代码执行前报错。
例子:C#、Java、Python(在类型注解的支持下)等都是强类型语言。
弱类型定义:弱类型语言在处理变量时类型约束较少,允许隐式类型转换,有时甚至允许不同类型之间的操作而不报错。
例子:JavaScript在早期版本中被认为是弱类型的,因为它允许像 "5" + 3 这样的操作,自动将字符串转换为数字。
强类型优势:减少错误,提高性能,更好的工具支持
弱类型优势:灵活性,动态类型语言
许多现代语言和框架结合了强类型和弱类型的优点。例如,JavaScript引入了类型注解(如 TypeScript),而Python和Ruby等语言提供了可选的类型提示。
30、Math.Round(11.5)等于多少?Math.Round(-11.5)等于多少
Math.Round(11.5)=12
Math.Round(-11.5)=-12
31、&和&&的异同
相同点:
&和&&都可作为逻辑与的运算符,表示逻辑与(and),当运算符两边的表达式结果都为true时,器结果才为true,否则,只要有一方为false,则结果为false。
不同点:
if(loginUser!=null&&string.IsnullEmpty(loginUser.UserName))
&&具有短路功能,即如果第一个表达式flase,则不再计算第二个表达式,对于上面的表达式,当loginUser为null时,后面表达式不会执行,不会报错NullPointerException。如果&&改为&,则会。所以当用到逻辑与的时候&是毫无意义的。&是位运算符
总结:&是位运算符,返回结果是int类型;&&是逻辑运算符,返回结果是bool类型。
32、i++和++i有什么区别
1)i++是先赋值,然后再自增;++i是先自增,后赋值。
2)
int i = 1;
int a = i++; // a 是 1,i 现在是 2
int b = ++i; // b 是 3,i 现在是 3
33、as和is的区别
as在转换的同时判断兼容性,如果无法进行转换,返回为null(没有产生新的对象),as转换是否成功判断的依据是是否为null;is只是做类型兼容性判断,并不执行类型转换,返回true或false,对象为null也返回false。
as效率更高,as只做一次类型兼容性检查。
34、谈谈finally用法。
finally:用于try{}catch{}finally{}结构,用于异常处理时执行任何清除操作。
特点:总是执行,无返回值,在 catch 之后,不捕获异常,资源清理
try
{// 可能会抛出异常的代码
}
catch (IOException ioEx)
{// 处理 IO 异常
}
catch (Exception ex)
{// 处理其他类型的异常
}
finally
{// 清理代码,比如关闭文件if (fileStream != null){fileStream.Close();}
}
35、简述C#成员修饰符
abstract:指示该方法或属性没有实现。
const:指定域或局部变量的值不能被改动。
event:声明事件。
extern:指示方法在外部实现。
override:对由基类继承成员的新实现。
readonly:指示一个域只能在声明时和相同类内部被赋值。
static:指示一个成员属于类型本身,而不是属于特定对象。
virtual:指示一个方法或存取器的实现可以在继承类中被覆盖。
36、什么是匿名类,有什么好处?
不用定义、没有名字的类,使用一次便可丢弃,LINQ查询中,匿名类经常用来创建查询结果的投影。好处是简单、随意、临时的。
// 创建匿名类的新实例
var anonymousObject = new
{Name = "Kimi",Age = 25,IsEmployee = true
};// 使用匿名类的实例
Console.WriteLine(anonymousObject.Name); // 输出: Kimi
Console.WriteLine(anonymousObject.Age); // 输出: 25
37、什么是逐字字符串
逐字字符串(Verbatim String)是一种使用 @ 符号开头的字符串字面量,它允许开发者在字符串中包含转义序列,而不需要实际执行转义。逐字字符串可以包含通常需要转义的字符,如双引号、单引号、反斜杠等,而不需要使用反斜杠进行转义。
// 普通字符串,需要转义双引号
string normalStr = "He said, \"Hello!\"";// 逐字字符串,不需要转义双引号
string verbatimStr = @"He said, "Hello!"";// 包含转义序列的逐字字符串
string path = @"C:\Program Files\MyApp";
38、列举你知道数字格式化转换
1)固定小数点格式 (F): 指定小数点后有固定数量的位数
double num = 123.456;
string formatted = num.ToString("F2"); // 结果: "123.46"
2)科学计数法 (E 或 e): 将数字表示为科学计数法。
string formatted = num.ToString("E2"); // 结果: "1.23E+02"
3)百分比格式 (P 或 p): 将数字乘以100并显示为百分比。
string formatted = num.ToString("P2"); // 结果: "12.35 %"
4)货币格式 (C 或 c): 根据当前区域设置将数字格式化为货币。
string formatted = 123456.78.ToString("C"); // 结果可能: "$123,456.78"
5)十六进制格式 (X 或 x): 将数字格式化为十六进制字符串。
int num = 255;
string formatted = num.ToString("X"); // 结果: "FF"
39、字符串拼接、字符串内插法
字符串拼接
是通过使用 + 运算符将多个字符串连接在一起。这是一种简单直接的方法,但在循环或多次拼接时可能会影响性能,因为字符串在C#中是不可变的。每次使用 + 运算符拼接字符串时,实际上都会创建一个新的字符串对象。
string part1 = "Hello";
string part2 = "World";
string result = part1 + " " + part2; // 结果: "Hello World"
字符串内插法
是一种更现代、更简洁的方法,它允许直接将变量或表达式的值插入到字符串中。从C# 6.0开始引入了字符串内插法,使用 $ 符号开头的字符串字面量,并使用花括号 {} 来包含要插入的变量或表达式。
string name = "Kimi";
int age = 25;
string message = $"Hello, my name is {name} and I am {age} years old.";
// 结果: "Hello, my name is Kimi and I am 25 years old."
40、什么是虚函数?什么是抽象函数?
虚函数:没有实现的,可以由子类继承并重写的函数。
抽象函数:规定其非虚子类必须实现的函数,必须被重写。
41、什么是WebService
WebService是基于网络的、分布式的模块化组件,它执行特定的任务,遵循具体技术规范,这些规范使WebService能够与其他兼容组件互操作。
42、ADO.NET常用对象有哪些
Connection:主要是开启程序和数据库之间的连接。没有利用连接对象将数据库打开,是无法从数据库中取得数据。Close和Dispose的区别,Close以后还可以Open,Dispose则不能。
Command:主要用来对数据库发出指令,例如对数据库下达增删改查命令,以及调用存储过程等。Command对象是通过Connection对象连接到数据员。
DataAdapter:是一个在数据提供者和应用程序之间的桥梁,用于填充数据到 DataSet 或 DataTable 对象中,并且可以用来更新数据库。DataAdapter 负责执行数据库查询,并将结果映射到内存中的 DataSet 或 DataTable 中,同时它还处理数据库的更新操作。
// 创建数据库连接
using (SqlConnection connection = new SqlConnection(connectionString))
{// 创建 SqlDataAdapter 实例using (SqlDataAdapter dataAdapter = new SqlDataAdapter("SELECT * FROM Customers", connection)){// 创建 DataSet 实例DataSet customersDataSet = new DataSet();// 使用 Fill 方法填充 DataSetdataAdapter.Fill(customersDataSet, "Customers");// 修改 DataSet 中的数据...// 更新数据库dataAdapter.Update(customersDataSet, "Customers");}
}
DataSet:这个对象可视为暂存区(Cache),可以把数据库查询到的数据保留显示,是放在内存中的。DataSet包含若干DataTable,DataTableTable又包含若干DataRow。
DataReader:当我们只需读取数据不需要操作数据时,可以使用DataReader对象。它是一次次向下循序读取数据源数据的,这些数据存在数据库中,不是一次性加载到程序内存,数据只读。
43、在ASP.NET中所有自定义用户控件必须继承自
Control类
44、为什么在.NET托管代码中我们不必担心内存泄漏
GC垃圾收集器,自动回收
45、MVC模式
MVC(Model-View-Controller)模型-视图-控制器
aspx就是View-视图;Model:DataSet、Reader、对象;Controller-控制器,cs代码。
Mvc是典型的平行关系,不是上下级,模型负责业务领域,视图负责界面显示,控制器负责数据读取填充模型,并把模型交给视图处理。好处是将页面和逻辑分离。
46、foreach遍历访问对象的要求
需要实现IEnumerable接口或者什么GetEnumerable方法的类型。
47、什么是反射?
反射(Reflection)是.NET框架提供的一种能力,它允许程序在运行时(Runtime)检查和操作自身的类型信息。使用反射,你可以获取类型的属性、方法、构造函数等信息,甚至可以创建和修改类型的实例。
// 获取类型的 Type 对象
Type type = typeof(ExampleClass);// 获取类型的方法
MethodInfo methodInfo = type.GetMethod("ExampleMethod");// 调用方法
object result = methodInfo.Invoke(new ExampleClass(), new object[] { /* 参数列表 */ });// 访问字段
FieldInfo fieldInfo = type.GetField("ExampleField");
object fieldValue = fieldInfo.GetValue(new ExampleClass());
48、ORM中延迟加载与直接加载有什么异同
延迟加载只在真正进行数据操作的时候进行加载数据,可以减少不必要的开销。
49、简述Func与Action区别
Func是有返回值的委托,Action是没有返回值的委托。
50、23种设计模式分别叫什么,如何分类。
分三类:创建型,行为型,结构型
创建型包括:单例模式,工厂模式,建造者模式,原型模式,工厂方法模式。
行为型包括:策略模式,模板方法模式,观察者模式,迭代器模式,责任链模式,命令模式,备忘录模式,状态模式,访问者模式,中介者模式,解释器模式。
结构型包括:适配器模式,装饰器模式,代理模式,外观模式,桥接模式,组合模式,享元模式
51、数组和集合的区别
数组用与保存固定数量的数据,定长,占用内存少,遍历速度快;
集合保存的数据数量,可以在程序的执行过程中,不断发生变化,占用内存多,遍历速度慢;
在功能上,数组所有功能,集合都能实现。
使用场景:
数组:适用于元素数量已知且不变,且需要频繁通过索引访问元素的场景。
集合:适用于需要动态添加或删除元素,或者需要使用集合的内置方法的场景。
52、面向对象三大特征,面向对象和面向过程的区别
封装、继承、多态
封装(Encapsulation):
封装是将数据(属性)和操作这些数据的方法组合在一起的过程。
它隐藏了实现细节,只暴露出一个可以被外界访问的接口。
封装还意味着使用访问修饰符(如 public、private、protected)来限制对类成员的访问。
继承(Inheritance):
继承是一种机制,允许一个类(子类或派生类)继承另一个类(基类或父类)的属性和方法。
继承支持代码复用,并且可以创建层次结构。
子类可以扩展或修改基类的行为。
多态(Polymorphism):
多态是指对象能够采取多种不同形式的能力。
它允许将不同类的对象视为同一类型,通常是通过接口或基类引用。
多态可以通过虚方法、覆盖(override)和方法重载(overloading)实现。
面向对象编程与面向过程编程的区别:
编程范式:
面向对象编程是一种基于“对象”的编程范式,它使用对象来设计和构建程序。
面向过程编程是一种基于“过程”的编程范式,它使用过程或函数来解决问题。
模块化:
面向对象编程强调高内聚、低耦合的模块化设计。
面向过程编程可能更侧重于将问题分解为一系列的过程。
可维护性和扩展性:
面向对象编程通常提供更好的可维护性和扩展性,因为对象和类可以独立修改和扩展。
面向过程编程可能在大型项目中更难维护和扩展,因为过程间的依赖关系可能更复杂。
适用场景:
每种编程范式都有其适用场景。面向对象编程适合于大型、复杂的系统,它强调了数据和功能的封装以及对象之间的交互。面向过程编程适合于逻辑简单、结构清晰的小型程序,它侧重于执行一系列的过程或函数。