回答1:接口能够继承接口,并且能够继承多个接口,用“,”进行分割,接口不容许直接或间接地从自身继承。和类的继承类似,接口的继承也造成接口之间的层次结构javascript
回答2:抽象类是能够实现接口的,抽象类里能够有抽象方法,也能够有具体的实现方法,也就是说继承了接口后也是能够实现接口里定义的方法
参考文章:html
修饰访问符这个算是挺基础的了,不过也不能忘记哦前端
参考文章:
1.访问修饰符(C# 编程指南)java
全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域, 未初始化的全局变量和未初始化的静态变量在相邻的另外一块区域。 当类首次被加载时static定义的变量被分配空间,程序结束后由系统释放.
若是在一个程序里过多的使用static定义的成员,确实很占内存,由于他的生命周期是整个程序,程序运行时没法被gc所回收,直到程序结束,释放内存.jquery
参考文章:web
这题我tm面试的几间都有啊,公司得有多懒sql
答案:会执行,在return后执行数据库
参考文章:编程
this 关键字引用类的当前实例,还可用做扩展方法的第一个参数的修饰符。
用途:
public Employee(string name, string alias) { // Use this to qualify the fields, name and alias: this.name = name; this.alias = alias; }
CalcTax(this);
public int this[int param] { get { return array[param]; } set { array[param] = value; } }
参考文章:
this(C# 参考)
这个要详细讲的话得要一本书吧,我就说大概。ASP.NET MVC包含了三部分,Model,View和Controller。Controller负责后台逻辑代码,View是纯净的HTML页面,Model是中间数据层。
前提固然是要搞懂这二者的联系了
三层架构是最基本的项目分层结果,而MVC则是三层架构的一个变体,MVC是一种好的开发模式。
首先你要明白MVC分别表明的是什么意思.
三层:UI 界面层 BLL 业务逻辑层,DAL数据访问层,Model 实体层
MVC中的的M 不是三层中的Model(实体层),他其实包括三层中的 BLL,DAL,Model,这是很是要注意的,这也是他们之间的区别的关键所在
三层是基于业务逻辑来分的,而mvc是基于页面来分的
MVC是 Model-View-Controller,严格说这三个加起来之后才是三层架构中的WEB层,也就是说,MVC把三层架构中的WEB层再度进行了分化,分红了控制器、视图、实体三个部分,控制器完成页面逻辑,经过实体来与界面层完成通话;而C层直接与三层中的BLL进行对话
参考文章:
关于AOP,它面向的是一个切面,可以把公共的功能抽出来,独立开发,而后将公共部分实现,在开发人员不知情的状况下,添加进去。而在MVC前台框架中,MVC中Controller中的Filter能够将公共的代码抽离出来。
Asp.Net MVC提供了如下几种默认的Filter:
Filter Type | 实现接口 | 执行时间 | Default Implementation |
---|---|---|---|
Authorization filter | IAuthorizationFilter | 在全部Filter和Action执行以前执行 | AuthorizeAttribute |
Action filter | IActionFilter | 分别在Action执行以前和以后执行。 | ActionFilterAttribute |
Result filter | IResultFilter | 分别在Action Result执行以后和以前 | ResultFilterAttribute |
Exception filter | IExceptionFilter | 只有在filter,或者 action method, 或者 action result 抛出一个异常时候执行 | HandleErrorAttribute |
参考文章:
微软官方提供的ORM工具,ORM让开发人员节省数据库访问的代码时间,将更多的时间放到业务逻辑层代码上。EF提供变动跟踪、惟一性约束、惰性加载、查询事物等。开发人员使用Linq语言,对数据库操做如同操做Object对象同样省事。
EF有三种使用场景,
ORM 是将数据存储从域对象自动映射到关系型数据库的工具。ORM主要包括3个部分:域对象、关系数据库对象、映射关系。ORM使类提供自动化CRUD,使开发人员从数据库API和SQL中解放出来。
DbContext是EntityFramework很重要的部分,链接域模型与数据库的桥梁,是与数据库通讯的主要类。
DbContext主要负责如下活动:
参考文章:
有三种方式:Code First、DBFirst、Model First
//Querying with LINQ to Entities using (var context = newSchoolDBEntities()) { var L2EQuery = context.Students.where(s => s.StudentName == "Bill"); var student = L2EQuery.FirstOrDefault<Student>(); } LINQ Query syntax: using (var context = new SchoolDBEntities()) { var L2EQuery = from st in context.Students where st.StudentName == "Bill"select st; var student = L2EQuery.FirstOrDefault<Student>(); }
//Querying with Object Services and Entity SQL string sqlString = "SELECT VALUE st FROM SchoolDBEntities.Students " + "AS st WHERE st.StudentName == 'Bill'"; var objctx = (ctx as IObjectContextAdapter).ObjectContext; ObjectQuery<Student> student = objctx.CreateQuery<Student>(sqlString); Student newStudent = student.First<Student>(); //使用EntityDataReader using (var con = newEntityConnection("name=SchoolDBEntities")) { con.Open(); EntityCommand cmd = con.CreateCommand(); cmd.CommandText = "SELECT VALUE st FROM SchoolDBEntities.Students as st where st.StudentName='Bill'"; Dictionary<int, string> dict = newDictionary<int, string>(); using (EntityDataReader rdr = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.CloseConnection)) { while (rdr.Read()) { int a = rdr.GetInt32(0); var b = rdr.GetString(1); dict.Add(a, b); } } }
using (var ctx = newSchoolDBEntities()) { var studentName = ctx.Students.SqlQuery("Select studentid, studentname, standardId from Student where studentname='Bill'").FirstOrDefault<Student>(); }
提及题,咱们不禁得会想到几个名词:栈和堆,值类型和引用类型,装箱和拆箱。
这些概念但是C#的入门基础呀,我们仍是要搞懂的,详细能够查看参考文章。
这里要提下一个知识点:C#新手都有一个误区:值类型的值都是保存在栈里,实际应该是:值类型的值是在它声明的位置存储的。即局部变量(参数)的值会在栈里,而当值类型做为引用类型的类型成员的话,会跟随对象,即存储在托管堆里。
顺便提供几张经典图片便于读者理解:
最后在这些概念里,我以为比较重要的精华提要:
参考文章:
最普通的用法固然就是:
效率上:s.Length == 0 > s == string.Empty > s == ""
不过 net 2.0后,可用String.IsNullOrEmpty(s) 来进行判断
参考文章:
String.IsNullOrWhiteSpace和String.IsNullOrEmpty的区别
关于lock的介绍就到这里,有下面几点须要注意的地方
还有摘自本篇评论的精彩回复:
this 表示的就是当前实例,当你再new一个的时候,锁定的就再也不是同一个对象了。 不能锁定值类型的缘由是,当这个值类型传递到另外一个线程的时候,会建立一个副本,锁定的也再也不是同一个对象了。 锁定字符串带来的问题是,字符串在CLR中会暂存在 内存中,若是有两个变量被分配了相同的字符串内容,那么这两个引用会指向同一块内存,实际锁定也就是同一个对象,这就会致使整个应用程序的阻塞。因此锁定字符串是很是危险的行为。
参考文章:
1.[C#基础]说说lock到底锁谁?](http://www.cnblogs.com/wolf-sun/p/4209521.html)
这篇已经有提过了:请参阅:最近找工做面的面试题目汇总(一)
参考文章:
为了将方法声明为能够接受可变数量参数的方法,咱们可使用params关键字来声明数组
要求:
参考文章:
string url=Request.Url.ToString();
参考文章:
这个我就不说了。 ?:
Queue是先进先出(first in first-out)数据结构,表示放进queue的第一个数据,会是第一个拿出来使用
示例:
//创建Queue的对象 var myqueue = new Queue<string>(); //新增数据进入queue myqueue.Enqueue("第1个"); myqueue.Enqueue("第2个"); myqueue.Enqueue("第3个"); //查看queue的全部资料 foreach (string queue in myqueue) { Console.WriteLine(queue); } //使用Peek()方法查看queue里的第一条数据 Console.WriteLine(""); Console.WriteLine("使用peek方法的輸出值:" + myqueue.Peek()); //使用Dequeue()方法从queue中拿出值 //记得是先进先出的获取方法 Console.WriteLine("第一个被我拿走了:" + myqueue.Dequeue()); //查看剩下的值 Console.WriteLine("查看myqueue剩下的值"); foreach (string queue in myqueue) { Console.WriteLine(queue.ToString()); } //查看某位置的值 Console.WriteLine("查看特定位置的值"); Console.WriteLine(myqueue.ElementAt(1));
运行结果
第1个
第2个
第3个
使用peek方法的輸出值:第1个 第一个被我拿走了:第1个 查看myqueue剩下的值 第2个 第3个 查看特定位置的值 第3个 第3个 第2个 第1个 Peek看到的数据:第3个 被拿走了:第3个 查看剩下的数据 第2个 第1个
Stack为后进先出(first-in last-out)的数据结构,表示第一个进去的数据,反而是最后一个出来。
示例代码
//创建Stack对象 var mystack = new Stack<string>(); //插入数据 mystack.Push("第1个"); mystack.Push("第2个"); mystack.Push("第3个"); //查看数据 foreach(string stack in mystack) { Console.WriteLine(stack.ToString()); } //Stack与Queue同样有Peek方法查看第一条数据 Console.WriteLine(""); Console.WriteLine("Peek看到的数据:"+mystack.Peek()); //使用Pop方法取出数据 Console.WriteLine("被拿走了:"+mystack.Pop()); Console.WriteLine("查看剩下的数据"); foreach (string stack in mystack) { Console.WriteLine(stack.ToString()); }
运行结果
第3个 第2个 第1个 Peek看到的数据:第3个 被拿走了:第3个 查看剩下的数据 第2个 第1个
参考文章:
重载应该叫overload,重载某个方法是在同一个类或父子关系类中发生的!重载(overload)是提供了一种机制, 相同函数名经过不一样的返回值类型以及参数来表来区分的机制
overload: 同一类中或父子关系类中皆可.
public string ToString(){return "a";} public string ToString(int id){return id.ToString();}
重写叫override,重写是在子类中重写父类中的方法。重写(override)是用于重写基类的虚方法,这样在派生类中提供一个新的方法
override: 父类:public virtual string ToString(){return "a";} 子类:public override string ToString(){return "b";}
很本质的区别就是看函数特征:覆写(Override)的两个函数的函数特征相同,重载(Overload)的两个函数的函数名虽然相同,但函数特征不一样。
参考文章:
## 9. using的意义
简述:
提供能确保正确使用 IDisposable 对象的方便语法。它的用途就是清理非托管资源,不受GC控制的资源。Using结束后会隐式的调用Disposable方法
如下两段代码的做用是一致的
using (Font font1 = new Font("Arial", 10.0f)) { byte charset = font1.GdiCharSet; }
{
Font font1 = new Font("Arial", 10.0f); try { byte charset = font1.GdiCharSet; } finally { if (font1 != null) ((IDisposable)font1).Dispose(); } }
参考文章:
由于ArrayList存在不安全类型与装箱拆箱的缺点,因此出现了泛型的概念。List类是ArrayList类的泛型等效类,它的大部分用法都与ArrayList类似,由于List类也继承了IList接口。最关键的区别在于,在声明List集合时,咱们同时须要为其声明List集合内数据的对象类型。
不能初始化的类被叫作抽象类,它们只提供部分实现,可是另外一个类能够继承它而且能建立它们
的实例。抽象类可以被用于类,方法,属性,索引器和事件,使用abstract 在一个类声明中表示该类倾向要做为其它类的基类,成员被标示成abstract,或被包含进一个抽象类,必须被其派生类实现。
一个抽象类必须为全部的接口成员提供实现
一个用于实现接口的抽象类可能把接口方法安排到抽象方法上。例如
interface I { void M(); } abstract class C: I { public abstract void M(); }
虚方法(virtual)和抽象方法(abstract)的区别
虚方法与非虚方法的最大不一样是,虚方法的实现能够由派生类所取代,这种取代是经过方法的重写实现的。
//抽象方法 public abstract class Animal { public abstract void Sleep(); public abstract void Eat(); } //虚方法 public class Animal { public virtual void Sleep(){} public virtual void Eat(){} }
public class Animal { public abstract void Sleep(); public abstract void Eat(); }
编译器会报错:
Main.cs(10): 'VSTest.Animal.Sleep()' is abstract but it is contained in nonabstract class 'VSTest.Animal'
Main.cs(11): 'VSTest.Animal.Eat()' is abstract but it is contained in nonabstract class 'VSTest.Animal'
public abstract class Animal { public abstract void Sleep(); public abstract void Eat(); } public class Cat : Animal { public override void Sleep() { Console.WriteLine( "Cat is sleeping" ); } // we need implement Animal.Eat() here }
编译器会报错:Main.cs(14): 'VSTest.Cat' does not implement inherited abstract member 'VSTest.Animal.Eat()'
由于咱们没有实现抽象类中全部抽象方法。
它不属于类的某一个具体的实例,而是属于类自己。因此对静态方法不须要首先建立一个类的实例,而是采用类名.静态方法的格式 。
static方法是类中的一个成员方法,属于整个类,即不用建立任何对象也能够直接调用!
static内部只能出现static变量和其余static方法!并且static方法中还不能使用this....等关键字..由于它是属于整个类!
C#中的方法有两种:实例方法,静态方法.
静态方法中用:
string className = System.Reflection.MethodBase. GetCurrentMethod().ReflectedType.FullName;
非静态方法中还能够用:
string className = this.GetType().FullName;
定义:静态构造函数用于初始化任何 静态 数据,或用于执行仅需执行一次的特定操做。 在建立第一个实例或引用任何静态成员以前,将自动调用静态构造函数。
静态构造函数具备如下特色:
尽可能避免使用继承来实现组建功能,而是使用黑箱复用,即对象组合。由于继承的层次增多,形成最直接的后果就是当你调用这个类群中某一类,就必须把他们所有加载到栈中!后果可想而知。(结合堆栈原理理解)。同时,有心的朋友能够留意到微软在构建一个类时,不少时候用到了对象组合的方法。好比 asp.net中,Page类,有Server Request等属性,但其实他们都是某个类的对象。使用Page类的这个对象来调用另外的类的方法和属性,这个是很是基本的一个设计原则;
若是抽象类实现接口,则能够把接口中方法映射到抽象类中做为抽象方法而没必要实现,而在抽象类的子类中实现接口中方法。
如下是我在网上看到的几个形象比喻。
1.飞机会飞,鸟会飞,他们都继承了同一个接口“飞”;可是F22属于飞机抽象类,鸽子属于鸟抽象类;
2. 就像铁门木门都是门(抽象类),你想要个门我给不了(不能实例化),但我能够给你个具体的铁门或木门(多态);并且只能是门,你不能说它是窗(单继承),一个门能够有锁(接口)也能够有门铃(多实现)。门(抽象类)定义了你是什么,接口(锁)规定了你能作什么(一个接口最好只能作一件事,你不能要求锁也能发出声音吧(接口污染))。
学习闭包:
(2).javascript的闭包
(3).图解闭包