C#小知识

1.表连接的SQL语句,对于内连接 inner join来说,join语句和把条件写在where语句里结果一样,但是对于左连接和右连接就不一样了,例如左连接,on后面的条件只对右表有效,对左表的筛选就要写在where里面。而且join on是先把两张表笛卡儿积组成一张表,再用where条件筛选,对于join很多表来说,从左往右,左边的表越小效率越高。所以尽量把条件写在on里面可以提高效率。

2.用Dapper框架的时候,尽量不要用拼接字符串的形式组SQL,因为有被攻击或者SQL注入的风险,尽量用StringBulder。

Dapper.Query()  返回查询结果                            参数一般为  SQL语句,参数变量,事务,SQL类型(SQL语句或者存储过程)

Dapper.Execute() 返回受影响的行数

GET请求和POST请求

1.GET和POST是http协议的两种请求方式,GET一般用来请求数据,POST一般用来传递参数用于更新等。

2.GET请求会把参数带在URL,对用户是可见的,而POST是把参数放到请求体中,但GET也可以把参数放到请求体中,但是服务器不一定能接收到

3.POST请求相对于GET请求更安全。因为GET请求传递的参数会显示在url中,用户在访问的时候浏览器会缓存网页,这样别人在查看浏览器浏览记录的时候会获取私人信息,POST请求不会被用户看到,所以安全性高。

4.GET请求在URL中传送的参数是有长度限制的,而POST么有。

5.对参数的数据类型,GET只接受ASCII字符,而POST没有限制。

6.对于GET方式的请求,浏览器会把http header和data一并发送出去,服务器响应200(返回数据);

而对于POST,浏览器先发送header,服务器响应100 continue,浏览器再发送data,服务器响应200 ok(返回数据)。但并不是所有浏览器都会在POST中发送两次包,Firefox就只发送一次。

EntityFrameWork 和 .NET Core对比

不能说Core一定比EF好,但是Core有一个最大的优点是跨平台,开源,而且比较多的IDE支持Core(VS ,VS CODE),而EF相对来说更加稳定,EF应用也更广泛,另外WCF服务和窗体不支持Core

但是当客户有以下需求时我们更应该考虑Core

  • 用户有跨平台需求。
  • 用户正在面向微服务(Azure)。
  • 用户正在使用 Docker 容器。
  • 需要高性能和可扩展的系统。
  • 需按应用程序提供并行的 .NET 版本(不同版本的.net core(可能是2.0 和3.0),像EF可能就是4.0  或者 4.1)。

3.String和StringBuilder

string本身是不可改变的,它只能赋值一次,每一次内容发生改变,都会生成一个新的对象,然后原有的对象引用新的对象,而每一次生成新对象都会对系统性能产生影响,这会降低.NET编译器的工作效率

而StringBuilder类则不同,每次操作都是对自身对象进行操作,而不是生成新的对象,其所占空间会随着内容的增加而扩充

当程序中需要大量的对某个字符串进行操作时,应该考虑应用StringBuilder类处理该字符串,其设计目的就是针对大量string操作的一种改进办法,避免产生太多的临时对象;而当程序中只是对某个字符串进行一次或几次操作时,采用string类即可。

4.ASP.NET和.NET的区别:

.Net是平台,下面包括很多种语言,比如C#,VB,C++等,而且.NET有主要分为两部分,WinForm(CS)和WebForm(BS),而ASP.NET属于.NET下的一部分,主要用来做WebForm项目。编译后形成CLR(中间语言),然后通过服务器的IIS+.Net FrameWork再次编译来运行。


5.委托是一个类,它定义了方法的类型,使得可以将方法当作另一个方法的参数来进行传递,这种将方法动态地赋给参数的做法,可以避免在程序中大量使用If-Else(Switch)语句,同时使得程序具有更好的可扩展性。

用法可以参考这篇博客  https://www.cnblogs.com/yinqixin/p/5056307.html


6.装箱与拆箱

装箱就是隐式的将一个值型转换为引用型对象。
拆箱就是将一个引用型对象转换成任意值型。
比如:
int i=0;
Syste.Object obj=i;
这个过程就是装箱!就是将 i 装箱!

比如:
int i=0;
System.Object obj=i;
int j=(int)obj;
这个过程前2句是将 i 装箱,后一句是将 obj 拆箱!

7.BS和CS架构的优缺点

B/S 浏览器端/服务端 : 开发成本低,版本永远是最新的,适用范围广,对安全的控制能力相对弱, 面向是不可知的用户群.   
C/S 客户端/服务端:通讯成本低,需要安装客户端,手动升级

8.DataReader和DataSet

两者最大的区别在于,DataReader使用时始终占用SqlConnection,在线操作数据库.任何对SqlConnection的操作都会引发DataReader的异常.因为DataReader每次只在内存中加载一条数据,所以占用的内存是很小的..因为DataReader的特殊性和高性能.所以DataReader是只进的.你读了第一条后就不能再去读取第一条了.

DataSet为离线操作数据,DataSet会将数据一次性读入内存,然后断开连接,这时其它操作就可以使用SqlConnection连接对象。因为DataSet将数据全部加载在内存中.所以比较消耗内存.但是确比DataReader要灵活.可以动态的添加行,列,数据.对数据库进行回传更新操作


9.在c#中using和new这两个关键字有什么意义?using 指令和语句 new 创建实例 new 隐藏基类中方法。
  using 引入名称空间或者使用非托管资源,相当于 try catch finally 使用完对象后自动执行实现IDisposable接口的类的Dispose方法释放对象资源
  new 新建实例或者修饰一个方法,表示此方法完全重写(即隐藏基类方法)

10.  虚函数  /  抽象函数  /  接口  /  静态函数
①虚函数:有实现体,实现多态性,子类可以重写也可以不重写直接拿来用。用Virtual 修饰,只能被单继承
②抽象函数:是一个类,有构造函数,用abstract修饰,没有实现体,非虚子类必须重写,有抽象方法一定是抽象类,但抽象类不一定有抽象方法。只能被单继承

③接口:不是类,没有构造函数,支持多态,用 Interface修饰,没有实现体,子类必须重写,支持多继承

④静态函数:用static修饰,第一次使用时被初始化,对于该类的所有对象来说,static成员变量只有一份,static方法中不可访问非static的成员。
 类定义前面放置关键字 sealed,可以将类声明为密封类。当一个类被声明为 sealed 时,它不能被继承。抽象类不能被声明为 sealed。
 
 11.重载与重写

重载:同一方法名,参数不同,或者参数个数不同,是多太的一种体现,或者是返回值的不同,或者是修饰符不同
重写:继承父类,对父类的方法重写
 override(重写)
   1、方法名、参数、返回值相同。
   2、子类方法不能缩小父类方法的访问权限。
   3、子类方法不能抛出比父类方法更多的异常(但子类方法可以不抛出异常)。
   4、存在于父类和子类之间。
   5、方法被定义为final不能被重写。
 overload(重载)
  1、参数类型、个数、顺序至少有一个不相同。 
  2、不能重载只有返回值不同的方法名。
  3、存在于父类和子类、同类中。

12.类和结构有以下几个基本的不同点:
类是引用类型,结构是值类型。
结构不支持继承。
结构不能声明默认的构造函数。
类的对象是存储在堆空间中,结构存储在栈中。堆空间大,但访问速度较慢,栈空间小,访问速度相对更快

13.值类型和引用类型

值类型(如 char、int 和 float)、枚举类型和结构类型。
引用类型包括类 (Class) 类型、接口类型、委托类型和数组类型。

声明一个值类型变量,编译器会在栈上分配一个空间,这个空间对应着该值类型变量,空间里存储的就是该变量的值。

引用类型的实例分配在堆上,新对应的是栈中存储该值的内存分配地址


14.反射(Reflection)
优点:
1、反射提高了程序的灵活性和扩展性。
2、降低耦合性,提高自适应能力。
3、它允许程序创建和控制任何类的对象,无需提前硬编码目标类。
缺点:
1、性能问题:使用反射基本上是一种解释操作,用于字段和方法接入时要远慢于直接代码。因此反射机制主要应用在对灵活性和拓展性要求很高的系统框架上,普通程序不建议使用。
2、使用反射会模糊程序内部逻辑;程序员希望在源代码中看到程序的逻辑,反射却绕过了源代码的技术,因而会带来维护的问题,反射代码比相应的直接代码更复杂。
反射(Reflection)的用途
反射(Reflection)有下列用途:
它允许在运行时查看特性(attribute)信息。
它允许审查集合中的各种类型,以及实例化这些类型。
它允许延迟绑定的方法和属性(property)。
它允许在运行时创建新类型,然后使用这些类型执行一些任务。
C# 高级教程   https://www.runoob.com/csharp/csharp-attribute.html

15.泛型

当我们写一个带参的方法时,参数类型一般需要指定,Public void Test(int a)

但是类似于重方法载,会传入不同的参数类型时,我们可能会Public void Test(string b),Public void Test(datetime c),但是如果类型真的很多,这种方法显然不合适。

或者我们可以 Public void Test(Object a)  看起来一劳永逸,但实际上这个过程需要大量的装箱拆箱操作,如果访问量很大是十分消耗性能的。这个时候就可以用泛型   Public void Stack<T>



16.匿名方法:
在匿名方法中您不需要指定返回类型,它是从方法主体内的 return 语句推断的。
匿名方法是没有名称只有主体的方法。
匿名方法是通过使用 delegate 关键字创建委托实例来声明的
delegate void NumberChanger(int n);
...
NumberChanger nc = delegate(int x)
{
    Console.WriteLine("Anonymous Method: {0}", x);
};
https://www.runoob.com/csharp/csharp-anonymous-methods.html

17.多线程和线程锁:

https://blog.csdn.net/afei__/article/details/80468265
线程是轻量级进程
线程生命周期开始于 System.Threading.Thread 类的对象被创建时,结束于线程被终止或完成执行时
未启动状态:当线程实例被创建但 Start 方法未被调用时的状况。
就绪状态:当线程准备好运行并等待 CPU 周期时的状况。
不可运行状态:下面的几种情况下线程是不可运行的:
已经调用 Sleep 方法
已经调用 Wait 方法
通过 I/O 操作阻塞
死亡状态:当线程已完成执行或已中止时的状况。

进程中第一个被执行的线程称为主线程。

锁和死锁
这个是在多线程中用到,为了线程安全来使用线程锁控制资源的利用和释放,比如最直观的售票系统,同一张票只能在一个窗口卖,且剩余票不能是负数,否则就是线程不安全得
为了防止这种情况发生 加入了线程锁,但是使用不当,比如一个进程占用了一个资源,但是又去请求新的资源,但是新的资源被其他进程占用,他又没有释放当前资源,这样下一个进程请求该资源就会造成堵塞,也就是死锁,为了防止这种情况发生
加锁顺序(线程按照一定的顺序加锁)
加锁时限(线程尝试获取锁的时候加上一定的时限,超过时限则放弃对该锁的请求,并释放自己占有的锁)
死锁检测

18.IEnumberable和IQueryable和Tolist()

IEnumberable接口成为迭代器,就一个GetEnumberator()方法;它返回的是一IEnumberator对象这是一个可以循环访问集合的对象,IEnumberator是一个集合访问器。支持foreach语句,IEnumberator定义了Current属性,MoveNext和Reset两个方法;Current用来获取集合中的项,MoveNext方法只是将游标内部位置向前移动(就是移到下一个元素)

IQueryable继承IEnumberable接口,两者都是延时执行

IEnumerable<T> 泛型类在调用自己的SKip 和 Take 等扩展方法之前数据就已经加载在本地内存里了,实际使用时会在内存中执行后续方法获取结果,比较消耗内存,且会一直和数据库保持连接

而IQueryable<T> 是将Skip ,take 这些方法表达式翻译成T-SQL语句之后再向SQL服务器发送命令,它并不是把所有数据都加载到内存里来才进行条件过滤。但仍和数据库保持连接

Tolist()会立即执行,把结果加载到内存中,且和数据库断开连接。
 

19.viewbag和viewdata
ViewData和ViewBag一般用于View和Controller间传值,
ViewData是key值读取对应的value,ViewData["Name"] = "蝈蝈";
ViewBag是动态类型,使用时直接通过属性赋值即可,ViewBag.Message = "Your application description page.";

ViewData和ViewBag只在当前Action中有效,等同于View

ViewData和ViewBag中的值可以互相访问

20.消息队列

消息队列比作是一个存放消息的容器,当我们需要使用消息的时候可以取出消息供自己使用。

消息队列是分布式系统中重要的组件,使用消息队列主要是为了通过异步处理提高系统性能和削峰、降低系统耦合性。目前使用较多的消息队列有ActiveMQ,RabbitMQ,Kafka,RocketMQ

队列 Queue 是一种先进先出的数据结构,所以消费消息时也是按照顺序来消费的

消息队列最常用的是发布-订阅模式,还有点对点订阅模式(一个消息只有一个消费者)

使用消息队列进行异步处理之后,需要适当修改业务流程进行配合,比如用户在提交订单之后,订单数据写入消息队列,不能立即返回用户订单提交成功,需要在消息队列的订单消费者进程真正处理完该订单之后,甚至出库后,再通过电子邮件或短信通知用户订单成功。最常见的订票系统。

使用消息队列需要注意

①.保证消息的可靠性传输(如何处理消息丢失的问题)   https://blog.csdn.net/evilcry2012/article/details/87718450

②.如何保证消息的顺序性?  https://blog.csdn.net/evilcry2012/article/details/86715842

20.同步和异步

同步异步 指的是在客户端

同步意味着 客户端提出了一个请求以后,在回应之前只能等待

例子:你打电话问书店老板有没有《分布式系统》这本书,如果是同步通信机制,书店老板会说,你稍等,”我查一下",然后开始查啊查,等查好了(可能是5秒,也可能是一天)告诉你结果(返回结果)。

异步意味着 客户端提出一个请求以后,还可以继续提其他请求

例子:书店老板直接告诉你我查一下啊,查好了打电话给你,然后直接挂电话了(不返回结果)。然后查好了,他会主动打电话给你。在这里老板通过“回电”这种方式来回调。

阻塞非阻塞 指的是服务器端

阻塞意味着 服务器接受一个请求后,在返回结果以前不能接受其他请求

非阻塞意味着 服务器接受一个请求后,尽管没有返回结果,还是可以继续接受其他请求

21.构造函数和析构函数

析构函数:对象所在的函数已调用完毕时,系统自动执行析构函数。特别的一个类可以有多个构造函数,可根据其参数个数的不同或参数类型的不同来区分它们 即构造函数的重载。

析构函数:是一种特殊的方法。用于在撤销对象前,完成一些清理工作,比如:释放内存等。  但是一般GC(垃圾回收机制帮我们做掉了)

22.IIS和 IIS Express

IIS是一个系统服务,IIS Express则只是一个临时进程。

IIS需要我们安装,可以手动部署发布的应用程序,也可以直接运行程序会默认设置在IIS的Default Web Site中。有可视化界面

IIS Express集成在了VS中,用于调试,没有可视化界面,有配置文件。

23.枚举

枚举是一组命名整型常量。枚举类型是使用 enum 关键字声明的。

C# 枚举是值类型。换句话说,枚举包含自己的值,且不能继承或传递继承。

 enum Day { Sun, Mon, Tue, Wed, Thu, Fri, Sat };

    static void Main()
    {
        int x = (int)Day.Sun;
        int y = (int)Day.Fri;
        Console.WriteLine("Sun = {0}", x);
        Console.WriteLine("Fri = {0}", y);
    }                                                        

会输出

Sun = 0
Fri = 5

24.DataTable和DataSet

DataSet当成内存中的数据库,DataSet是不依赖于数据库的独立数据集合。所谓独立,就是说,即使断开数据链路,或者关闭数据库,DataSet依然是可用的,DataSet在内部是用XML来描述数据的,DataSet中可能有多个DataTable

DataTable是临时保存数据的网格虚拟表(表示内存中数据的一个表)

25.冒泡排序

int temp = 0;

int[] arr = {23, 44, 66, 76, 98, 11, 3, 9, 7};

for (int i = 0; i < arr.Length - 1; i++)

            {

                for (int j = 0; j < arr.Length - 1 - i; j++)

                {

                    if (arr[j] > arr[j + 1])

                    {

                        temp = arr[j + 1];

                        arr[j + 1] = arr[j];

                        arr[j] = temp;

                    }

                }

26. Skip(跳过) Take(获取) (C#里面集合的扩展方法,常用作分页)

var list = new  List<int>();

//比如 list里面是 1,2,3,4,5,6,7,8,9,10

var result = list.Skip(2);  //返回值就是 3,4,5,6,7,8,9,10;

var result = list.Take(2);  //返回值就是 1,2

//搭配使用,一般用来分页

var result = list.Skip(2).Take(2); //返回值 3,4

27.对比数组(Array)/集合(Set)/列表(List)
1、存储内容比较: Array 数组可以包含基本类型和对象类型, ArrayList 却只能包含对象类型。 Array 数组在存放的时候一定是同种类型的元素。ArrayList 就不一定了 。集合Set的对象都是不重复的,而且是无序的。

2、空间大小比较: Array 数组的空间大小是固定的,所以需要事前确定合适的空间大小。 ArrayList 的空间是动态增长的,而且,每次添加新的元素的时候都会检查内部数组的空间是否足够。

3.方法上的比较: ArrayList 方法上比 Array 更多样化,比如添加全部 addAll()、删除全部 removeAll()、返回迭代器 iterator() 等。

发布了45 篇原创文章 · 获赞 4 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/qq_36730649/article/details/80405030
今日推荐