1_DotNet Core

AspNetCoreHostingModel

  • 当它的值是InProcess的时候是进程内托管,也就是IIS托管的模式
  • 当它的值是OutOfProcess的时候是进程外托管,也就是将请求转发到后端的ASP.NET Core中,而整个应用程序是运行在ASP.NET CoreKestrel中的
  • 默认是OutOfProcess托管
    OutOfProcess默认有2个Web服务器-内部Web服务器和外部Web服务器
    内部Web服务器是Kestrel
    外部Web服务器是IIS,Niginx或者Apache

Kestrel Web Server

  • Kestrel是ASP.NET Core 的跨平台Web服务器
  • Kestrel本身可以用作边缘服务器
  • Kestrel中用于托管应用程序的进程是dotnet.exe

PackageReference

  • 用于包含对应用程序安装的nuget包的引用
  • Metapackeage(综合包)-Microsoft.AspNetCore.App
  • Metapackeage没有任何内容,只是一个列表
发表在 Core | 留下评论

ASP.net Core 亮点

统一了MVC和WebAPI编程模型

在MVC Controller和ASP.NET WebAPI 在这两种情况下,我们创建了Controller都从相同的Controller基类继承并且返回IActionResult

ViewResult和JsonResult 都统一由IActionResult来实现

提供了中间件组件

可以自己编写中间件

发表在 Core | 留下评论

SOLID

SRP:单一职责原则

表明一个类有且只有一个职责。一个类就像容器一样,它能添加任意数量的属性、方法等。

OCP:开闭原则

一个类应该对扩展开放,对修改关闭。这意味一旦创建了一个类并且应用程序的其他部分开始使用它,就不应该修改它。

LSP:里式替换原则

派生的子类应该是可替换基类的,也就是说任何基类可以出现的地方,子类一定可以出现。值得注意的是,当通过继承实现多态行为时,如果派生类没有遵守LSP,可能会让系统引发异常。

ISP:接口隔离原则

使用多个专门的接口比使用单一的总接口总要好。注意:在代码中应用ISP并不一定意味着服务就是绝对安全的。仍然需要采用良好的编码实践,以确保正确的验证与授权。
对于一个大型的系统功能,需要拆分为多个小功能,那么这个时候我们是写一个庞大的类来实现所有的功能接口呢,还是拆分多多个接口,并建立不同的实现类呢?
正确的选择是把单个接口分开,客户可以按需继承单一功能接口子类。

DIP:依赖倒置原则

表明高层模块不应该依赖低层模块,相反,他们应该依赖抽象类或者接口。这意味着不应该在高层模块中使用具体的低层模块。

发表在 C#, 设计模式 | 留下评论

windows Form 开发控件的事件时候需要注意的事情

第一 必须要注意IsDirty的变化

第二 最好将条件进行到最细致来实现方法

第三 事件的选择必须要要精确

比如CellEnter只有在进入控件的一瞬间会触发。
当操作Cell时候,同同时对Menu部分的控件进行操作时候,CellEnter的Focus不会离开,这时候如果Menu上的事件触发了类似取消编辑一类的方法时候。
再次点击Cell的时候,CellEnter会因为Focus没有离开而无法触发。
这时候最好使用CellBeginEdit事件。

发表在 Windows Form | 留下评论

C#面试手册

https://www.yuque.com/books/share/6b482362-b05e-4a41-944d-afd064bb84a6?#

发表在 C# | 留下评论

.NET/C#面试题汇总系列:基础语法

1. 字符串中string str=null和string str=””和string str=string.Empty的区别?

string.Empty相当于“”,Empty是一个静态只读的字段。 string str=”” ,初始化对象,并分配一个空字符串的内存空间 string str=null,初始化对象,不会分配内存空间

2. byte b = ‘a’; byte c = 1; byte d = ‘ab’; byte e = ‘啊’; byte g = 256; 这些变量有些错误是错再哪里?

本题考查的是数据类型能承载数据的大小。
1byte =8bit,1个汉字=2个byte,1个英文=1个byte=8bit
所以bc是对的,deg是错的。’a’是char类型,a错误
java byte取值范围是-128~127, 而C#里一个byte是0~255

3.string和StringBuilder的区别,两者性能的比较

都是引用类型,分配再堆上
StringBuilder默认容量是16,可以允许扩充它所封装的字符串中字符的数量.每个StringBuffer对象都有一定的缓冲区容量,当字符串大小没有超过容量时,不会分配新的容量,当字符串大小超过容量时,会自动增加容量。

对于简单的字符串连接操作,在性能上stringbuilder不一定总是优于strin因为stringbulider对象的创建也消耗大量的性能,在字符串连接比较少的情况下,过度滥用stringbuilder会导致性能的浪费而非节约,只有大量无法预知次数的字符串操作才考虑stringbuilder的使用。从最后分析可以看出如果是相对较少的字符串拼接根本看不出太大差别。

Stringbulider的使用,最好制定合适的容量值,否则优于默认值容量不足而频繁的进行内存分配操作,是不妥的实现方法。

参考链接:https://www.cnblogs.com/haofuqi/p/4826262.html

4.什么是扩展方法?

一句话解释,扩展方法使你能够向现有类型“添加”方法,无需修改类型

条件:按扩展方法必须满足的条件,1.必须要静态类中的静态方法2.第一个参数的类型是要扩展的类型,并且需要添加this关键字以标识其为扩展方法

建议:通常,只在不得已的情况下才实现扩展方法,并谨慎的实现

使用:不能通过类名调用,直接使用类型来调用


5.byte a =255;a+=5;a的值是多少?

byte的取值范围是-2的8次方至2的8次方-1,-256至258,a+=1时,a的值时0,a+=5时,a的值是0,所以a+=5时,值是4

6.什么是装箱和拆箱?

装箱就是隐式地将一个值类型转换成引用类型,如:

int i=0;
Syste.Object obj=i;

拆箱就是将引用类型转换成值类型,如:

int i=0;
System.Object obj=i;
int j=(int)obj;(将obj拆箱)



7.值类型和引用类型的区别

值类型变量是直接包含值。将一个值类型变量赋给另一个值类型变量,是复制包含的值,默认值是0。

引用类型变量的赋值只复制对对象的引用,而不复制对象本身,默认值是null
值类型有整形、浮点型、bool、枚举。

引用类型有class、delegate、Object、string

值类型存储在栈中,引用类型存储在堆中

8.new关键字的作用?

运算符:创建对象实例

修饰符:在派生类定义一个重名的方法,隐藏掉基类方法

约束:泛型约束定义,约束可使用的泛型类型,如:

public class ItemFactory<T> where T : IComparable, new()
   {
   }


9. int?和int有什么区别?

int?为可空类型,默认值可以是null

int默认值是0

int?是通过int装箱为引用类型实现


10. C#中的委托是什么?

一句话解释就是:将方法当作参数传入另一个方法的参数。 .net中有很多常见的委托如:Func 、Action 作用:提高方法的扩展性


11.用最有效的方法算出2乘以8等于几?

位运算是最快,使用的是位运算 逻辑左位移<<。 方法是2<<3相当于0000 0000 0000 0010 (2的16位int二进制)左移三位就是 0000 0000 0001 0000(16的二进制)


12.const和readonly有什么区别?

都可以标识一个常量。主要有以下区别:

  1. 初始化位置不同。const必须在声明的同时赋值;readonly即可以在声明处赋值,也可以在静态构造方法(必须是静态构造方法,普通构造方法不行)里赋值。
  2. 修饰对象不同。const即可以修饰类的字段,也可以修饰局部变量;readonly只能修饰类的字段
  3. const是编译时常量,在编译时确定该值;readonly是运行时常量,在运行时确定该值。
  4. const默认是静态的;而readonly如果设置成静态需要显示声明
  5. 修饰引用类型时不同,const只能修饰string或值为null的其他引用类型;readonly可以是任何类型。



13.现有一个整数number,请写一个方法判断这个整数是否是2的N次方

4(100)、5(101)、8(1000)、16(10000)

取模运算: 用number%2==0可以判断,但是这个有点低级

位运算:(使用位运算逻辑并,两个位上的都为1才是1,其余都是0,判断是否等于0)

4&3相当于100&011 ,结果是000等于0,所以4是2的n次方

5&4相当于101&100,结果是100不等于0,所以5不是2的n次方

如果要问如果是2的N次方,这个N是多少?这该怎么算?

private static byte get(int n)
    {
        byte number = 1;
        while (n/2!=1)
        {
            n = n / 2;
            number += 1;
        }
        return number;
    }



14.CTS、CLS、CLR分别作何解释

CTS:通用语言系统。CLS:通用语言规范。CLR:公共语言运行库。

CTS:Common Type System 通用类型系统。Int32、Int16→int、String→string、Boolean→bool。每种语言都定义了自己的类型,.Net通过CTS提供了公共的类型,然后翻译生成对应的.Net类型。

CLS:Common Language Specification 通用语言规范。不同语言语法的不同。每种语言都有自己的语法,.Net通过CLS提供了公共的语法,然后不同语言翻译生成对应的.Net语法。

CLR:Common Language Runtime 公共语言运行时,就是GC、JIT等这些。有不同的CLR,比如服务器CLR、Linux CLR(Mono)、Silverlight CLR(CoreCLR)。相当于一个发动机,负责执行IL。


15.在.net中,配件的意思是?

程序集。(中间语言,源数据,资源,装配清单)


16.分析下面代码,a、b的值是多少?

string strTmp = "a1某某某";
int a = System.Text.Encoding.Default.GetBytes(strTmp).Length;
int b = strTmp.Length;

分析:一个字母、数字占一个byte,一个中文占占两个byte,所以a=8,b=5


17.Strings = new String(“xyz”);创建了几个String Object?

两个对象,一个是“xyz”,一个是指向“xyz”的引用对象s。


18.静态成员和非静态成员的区别

  • 静态成员用statis修饰符声明,在类被实例化时创建,通过类进行访问
  • 不带statis的变量时非静态变量,在对象被实例化时创建,通过对象进行访问,
  • 静态方法里不能使用非静态成员,非静态方法可以使用静态成员
  • 静态成员属于类,而不属于对象


19.c#可否对内存直接操作

C#在unsafe 模式下可以使用指针对内存进行操作, 但在托管模式下不可以使用指针,C#NET默认不运行带指针的,需要设置下,选择项目右键->属性->选择生成->“允许不安全代码”打勾->保存


20.short s1 = 1; s1 = s1 + 1;有什么错? short s1 = 1; s1 += 1;有什么错?

s1+1不能显式转换成short类型,可以修改为s1 =(short)(s1 + 1) 。short s1 = 1; s1 += 1正确


21.什么是强类型,什么是弱类型?哪种更好些?为什么?

强类型是在编译的时候就确定类型的数据,在执行时类型不能更改,而弱类型在执行的时候才会确定类型。没有好不好,二者各有好处,强类型安全,因为它事先已经确定好了,而且效率高。

一般用于编译型编程语言,如c++,java,c#,pascal等,弱类型相比而言不安全,在运行的时候容易出现错误,但它灵活,多用于解释型编程语言,如javascript,vb,php等


22.using关键字的作用

  • 引用命名空间,也可using 别名
  • 释放资源,实现了IDisposiable的类在using中创建,using结束后会自定调用该对象的Dispose方法,释放资源。


23.ref和out有什么区别

1.都是按引用类型进行传递

2.属性不是变量不能作为out、ref参数传递

3.ref参数必须初始化。out不需要初始化

4.作用,当方法有多个返回值时,out非常有用

24.a.Equals(b)和a==b一样吗?

不一样,a==b仅仅表示a和b值相等,a.Equals(b)表示a与b一致


25.下面这段代码求值

class Class1
    {
        internal static int count = 0;
        static Class1()
        {
            count++;
        }
        public Class1()
        {
            count++;
        }
    }
    Class1 o1 = new Class1();
    Class1 o2 = new Class1();

o1.count的值是多少?

答案:3,静态 构造方法计算一次,两个实例化对象计算两次。


26.关于构造函数说法正确的是哪个?

a)构造函数可以声明返回类型。

b)构造函数不可以用private修饰

c)构造函数必须与类名相同

d)构造函数不能带参数

答案:c ,构造函数必须与类名相同,可以传递多个传递,作用就是便于初始化对象成员,不能有任何返回类型


27.Math.Round(11.5)等於多少? Math.Round(-11.5)等於多少?

Math.Round(11.5)=12

Math.Round(-11.5)=-12


28.&和&&的区别

相同点

&和&&都可作逻辑与的运算符,表示逻辑与(and),当运算符两边的表达式的结果都为true时,其结果才为true,否则,只要有一方为false,则结果为false。(ps:当要用到逻辑与的时候&是毫无意义,&本身就不是干这个的)

不同点
···
if(loginUser!=null&&string.IsnullOrEmpty(loginUser.UserName))
···
&&具有短路的功能,即如果第一个表达式为false,则不再计算第二个表达式,对于上面的表达式,当loginUser为null时,后面的表达式不会执行,所以不会出现NullPointerException如果将&&改为&,则会抛出NullPointerException异常。(ps:所以说当要用到逻辑与的时候&是毫无意义的)

& 是用作位运算的。

总结

&是位运算,返回结果是int类型 &&是逻辑运算,返回结果是bool类型


29. i和i有什么区别?

1.i++是先赋值,然后再自增;++i是先自增,后赋值。

2.i=0,i++=0,++i=1; Console.WriteLine(i==i); 结果位true


30.as和is的区别

as在转换的同时判断兼容性,如果无法进行转换,返回位null(没有产生新的对象),as转换是否成功判断的依据是是否位null is只是做类型兼容性判断,并不执行真正的类型转换,返回true或false,对象为null也会返回false。

as比is效率更高,as只需要做一次类型兼容检查

发表在 Uncategorized | 留下评论

Snippets创建一个自己的快捷输入指令

打开Visual Studio的上方的[工具]的[代码片段管理器],语言选择c#,然后选择[Visual C#]的文件夹,就能够到达Snippets的管理文件夹

然后就可以进行修改和添加了

这里我创建了一个propn指令的propn.snippet文件,将其存放在文件夹下,重启Visual Studio就可以使用了

<?xml version="1.0" encoding="utf-8"?>
<CodeSnippets xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">
	<CodeSnippet Format="1.0.0">
		<Header>
			<Title>propn</Title>
			<Shortcut>propn</Shortcut>
			<Description>属性和支持字段的代码片段</Description>
			<Author>Microsoft Corporation</Author>
			<SnippetTypes>
				<SnippetType>Expansion</SnippetType>
			</SnippetTypes>
		</Header>
		<Snippet>
			<Declarations>
				<Literal>
					<ID>type</ID>
					<ToolTip>属性类型</ToolTip>
					<Default>int</Default>
				</Literal>
				<Literal>
					<ID>property</ID>
					<ToolTip>属性名</ToolTip>
					<Default>MyProperty</Default>
				</Literal>
				<Literal>
					<ID>field</ID>
					<ToolTip>支持此属性的变量</ToolTip>
					<Default>myVar</Default>
				</Literal>
			</Declarations>
			<Code Language="csharp"><![CDATA[private $type$ $field$;

	public $type$ $property$
	{
		get { return $field$;}
		set { 
		        $field$ = value;
	                        this.RaisePropertyChanged("$property$");
		      }
	}
	$end$]]>
			</Code>
		</Snippet>
	</CodeSnippet>
</CodeSnippets>
发表在 C# | 留下评论

WPF中的MVVM 模式(Model-View-ViewModel )

1.MVVM概述

  • 在Winform
    • 指令传递(如Click):通过事件传递
    • 值的传递(TextBox.text):通过直接在后台调用控件直接传递
    • 所以当UI界面发生变更的时候,后端代码将会同时发生变更
  • 在wpf中,其实也可以是先上述的功能,同样也存在相同的缺点
  • 但是Wpf存在一个功能,叫做数据绑定binding:这个功能可以将数据属性和控件的属性进行绑定,所以View的控件只需绑定到数据属性就可以实现和后台的交互
  • 而数据属性我们使用VM来进行接受和处理

发表在 Wpf | 留下评论

Resources Binding

1.Resource的种类

  • Application.Resources 项目公用资源
  • Window.Resources 窗体公用资源
  • Control.Resources控制公用资源
  • Grid.Resource表格公用资源
  • 等等,只有当前组件和它的子组件可以使用

2.资源的静态绑定

<UserControl>   
    <!--创建一个FontFamily的元素,值是隶书,名称是 fontContent-->
    <Control.Resources>
        <FontFamily x:Key="fontContent">隶书</FontFamily>
    </Control.Resources>
 <Grid>
   <!--调用静态资源fontContent ,将其赋予FontFamily-->
   <TextBlock Grid.Row="6" Text="数据绑定" FontFamily="{Binding Source={StaticResource fontContent}, Path=Source}"/>
 </Grid>
</UserControl>

3.动态资源的绑定

RelativeSource中Mode=FindAncestor的情况(寻找相对父类)

<Grid x:Name="test1">
     <Grid>
         <TextBlock  Text="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorLevel=2,AncestorType={x:Type Grid}},Path=Name}"/>
     </Grid>
</Grid>

RelativeSource中Mode=Self 绑定自己


<Grid>
    <TextBlock Grid.Row="8" Width="30" Background="red" Height="{Binding RelativeSource={RelativeSource Mode=Self}, Path=Width}"/>
</Grid>

RelativeSource Mode=TemplatedParent 啥玩意儿?

发表在 Wpf | 留下评论

WPF 控件/元素绑定

1.Slider和TextBlock之间进行绑定(Xaml文本的操作)

  • ElementName=Slider1:(元素)对象的名称是Slider1
  • Path=Value :Slider1下面的属性的是Value
  • Mode下面有4个模式
    • TwoWay(defualt):
      ->代表双向绑定
    • OneWay:代表被绑定的对象改变引起主动绑定的对象改变
      如果如下代码,TextBox的Text绑定了Slider1的Value的时候,
      ->如果Slider1的Value变化,那么TextBox的Text变化
      ->如果TextBox的Text变化, Slider1的Value不会变化
    • OneTime:代表绑定只会执行一次,不会一直监听
      ->代表如果绑定只执行一次,下图代码会在初始化阶段执行
    • OneWayToSource: 代表主动绑定的对象改变引起被绑定的对象改变
      如果如下代码,TextBox的Text绑定了Slider1的Value的时候,
      ->如果Slider1的Value变化,那么TextBox的Text不会变化
      ->如果TextBox的Text变化, Slider1的Value变化
<Slider x:Name="Slider1" Maximum="100" Minimum="1" Grid.Row="0" VerticalAlignment="Center" TickPlacement="TopLeft" TickFrequency="2" Margin="10" />
<TextBlock x:Name="TextBlock1" Grid.Row="1"  FontSize="{Binding ElementName=Slider1, Path=Value, Mode=TwoWay}" Text="1"  TextAlignment="Center"/>
<TextBox x:Name="TextBox1" Grid.Row="2" Width="300" Height="50" Text="{Binding ElementName=Slider1, Path=Value, Mode=Default, UpdateSourceTrigger=PropertyChanged}" />

2.Slider和TextBlock之间进行绑定(后台代码操作)

<!--xaml代码-->
<TextBox x:Name="TextFontFamily" Grid.Row="5" Text=""/>
<TextBlock Grid.Row="6" Text="数据绑定" FontFamily="{Binding Source={StaticResource fontContent}, Path=Source}"/>

绑定

//实例化绑定,构造函数中的参数代表设置目标的属性
Binding binding = new Binding("Text");
//设置想要绑定的对象
binding.ElementName = "TextBox1";
//设置在Label1的Content属性上绑定TextBox1.Text
BindingOperations.SetBinding(Label1, System.Windows.Controls.Label.ContentProperty, binding);
//将Label1上的Content属性解绑
BindingOperations.ClearBinding(Label1, System.Windows.Controls.Label.ContentProperty);
//将Label1上的所有属性解绑
BindingOperations.ClearAllBindings(Label1);

3.属性和控件之间的绑定

  • Wpf规定,如果Binding如果只指定了path,没有指定source,那么就会将控件的DataContext用来当作source

代码如下

    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            this.DataContext = new MainWindowsViewModel();
        }
    }

控件代码如下

<TextBox x:Name="text_1" Grid.Row="1" FontSize="50" Text="{Binding Path = Text1}"/>
  • 属性代码如下需要注意的是当使用binding绑定了数据之后,例如textbox
    • 如果在控件上修改值,那么会导致属性的值发生改变
    • 但是如果属性值发生改变,和控件绑定不一样的是,必须使用INotifyPropertyChanged接口的PropertyChangedEventHandler事件处理器,将其激并且将相应的做出改变的属性名称传出
 internal class MainWindowsViewModel:NotifacationObject	{	
      private double _text1;
	  public double Text1
	{
	   get { return _text1; }
	   set {
		_text1 = value;
		this.RaisePropertyChanged("Text1");
	       }
	}
}

4.命令和控件之间的绑定

  • 首先控件是通过是同Command这个属性来绑定命令的(此处跟3一样,Source使用的是MainWindowsViewModel的实例)
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            this.DataContext = new MainWindowsViewModel();
        }
    }
<Button Content="Test" Command="{Binding Path=TestCommand}" />
  • 绑定的控件必须满足ICommand接口,且执行是执行的ICommand的Execute所实现的方法,CanExecute用可不用,Execute会默认传入一个object类型的parameter参数
internal class DelegateCommand : ICommand
    {
        public event EventHandler? CanExecuteChanged;

        public bool CanExecute(object? parameter)
        {
            if (this.CanExecutefuc == null) 
            {
                return true;
            }
            return this.CanExecutefuc(parameter);
        }

        public void Execute(object? parameter)
        {
            if (ExcuteAction == null) 
            {
                return;
            }
            this.ExcuteAction(parameter);
        }

        public Func<object,bool> CanExecutefuc { get; set; }
        public Action<object> ExcuteAction { get; set; }
    }
}

给DelegateCommand的委托参数赋值

 internal class MainWindowsViewModel:NotifacationObject	{
     //构造函数给委托赋值
     public MainWindowsViewModel()
     {
          this.TestCommand = new DelegateCommand();
          this.TestCommand.ExcuteAction = new Action<object>(this.Test);
     }	
     public DelegateCommand TestCommand { get; set; }
     private void Test(object parameter) 
     {
	Text1 = 3;
     }
}
发表在 Wpf | 留下评论