文章目录
using static(C#6)
Math
static double CalcCircleToArea(double radius) => Math.PI * Math.Pow(radius, 2);
//using static System.Math
static double CalcCircleToArea(double radius) => PI * Pow(radius, 2);
Reflection
var fields = type.GetFields(BindingFlags.Public | BindingFlags.NonPublic);
//using static System.Reflection.BindingFlags;
var fields = type.GetFields(Public | NonPublic);
String
//using static System.String; 普通类型也是没有任何问题
String[] arr = { "A", "B" };
Console.WriteLine(Join('-', arr));
对象初始化器
String txt = "This text needs truncating";
StringBuilder sb = new StringBuilder(txt)
{
Length = 10,
};
sb[9] = '\u2026';
Console.OutputEncoding = Encoding.UTF8;//确保Console支持Unicode编码
//===
String txt = "This text needs truncating";
StringBuilder sb = new StringBuilder(txt)
{
Length = 10,
[9]='\u2026',
};
Console.OutputEncoding = Encoding.UTF8;
集合初始化器
- 必须要实现 : IEnumerable
- 必须要含有 Add( ) , 扩展方法也可以
var dic = new Dictionary<String, Int32>//(C#3)
{
{"A",1 },
{"B",2 }
};
//第一种--Add(): Key重复会抛出异常ArgumentException
//第二种--[]: Key重复会替换
var dic = new Dictionary<String, Int32>//(C#6)
{
["A"] = 1,
["B"] = 2,
};
internal sealed class SchemalessEntity : IEnumerable<KeyValuePair<String, Object>>
{
private Dictionary<String, Object> m_Entys = new Dictionary<string, object>();
public String? Key { get; set; }
public String? ParentKey { get; set; }
public Object this[String key]
{
get => m_Entys[key];
set => m_Entys[key] = value;
}
public void Add(String key, Object value) =>
m_Entys.Add(key, value);
public IEnumerator<KeyValuePair<string, object>> GetEnumerator() =>
m_Entys.GetEnumerator();
IEnumerator IEnumerable.GetEnumerator() =>
GetEnumerator();
}
static void Main(String args[])
{
SchemalessEntity parent = new SchemalessEntity { Key = "key" };
SchemalessEntity child1 = new SchemalessEntity {
{"Name","柚子" },
{"School","千禧年" }
};
SchemalessEntity child2 = new SchemalessEntity
{
Key = "parent-key",
ParentKey = "parent-key",
["Name"] = "柚子",
["School"] = "千禧年",
};
}
internal static class Chapter
{ //List<T>也可以,但要推断出类型
public static void Add(this List<String> list, int value, int count = 1)
{
list.AddRange(Enumerable.Repeat(value.ToString(), count));
}
}
static void Main(String args[])
{
List<String> lst = new List<string>
{
{ 20,2 },
{ 40 },
60,
};
//===
lst.Add(20,2);
lst.Add(40);
lst.Add(60);
}
可空类型
Nullable<?>(C#2)
Nullable<int> test = new Nullable<int>();
/* test = ""; //编译错误,无法转换为int? */
test = 20;
if (test.HasValue)// === (test!=null)
{ //如果为NULL,则NullReferenceException
Console.WriteLine(test.GetType());//System.Int32
}
?(C#6)
String txt = null;
//NullReferenceException
String result = txt.ToUpper().Substring(0, 1);
//并不会抛出异常
String result = txt?.ToUpper()?.Substring(0, 1);
原理: 每遇到一个空值运算符,编译器都会为?.前面插入一条空值检查语句。如果为NULL,则整个表达式运算终止,并返回NULL值;
如果不为NULL,则表达式继续向右对属性、方法、字段或索引器进行运算,而不需要对左边的值重复运算。如果整个表达式式非
可空类型,一旦其中出现了空值条件运算符,整个表达式类型就会变成对应的可空类型。
String txt = null;
String result;
var temp1 = txt;
if (temp1 == null)
result = null;
else
{
var temp2 = temp1.ToUpper();
if (temp2 == null)
result = null;
else
result = temp2.Substring(0,1);
}
-
索引器
int[] arr = null; int? result = arr?[0];
-
事件
delegate void ClickEventHandler(); event ClickEventHandler Click; Click += null; //(C#6)之前 if (Click != null) Click(); //? Click?.Invoke();
-
编译错误
person?.Name = ""; person?.Age++; arr?[0] = 10;
空合并运算符(C#6)
bool? b = null;
Console.WriteLine(b == true);//False
Console.WriteLine(b == false);//False
Console.WriteLine(b == null);//True
//尝试执行比较操作,如果操作没有执行完,就采用??后的值
Console.WriteLine(b ?? true);//True
异常过滤器
对异常处理更多的控制,既可以根据异常类型,也可以根据异常数据来确定是否需要捕获异常。
try
{
throw new Exception("S");
}
catch (Exception E) when (E.Message.Contains("A"))
{
Console.WriteLine(E.Message);
}
catch (Exception E) when (E.Message.Contains("S"))
{
Console.WriteLine(E.Message);
}
局部方法(C#7)
1.限制
- 不能有访问修饰符
- sealed、virtual、abstract、new、override不能修饰
- 不能应用Attribute
- 不能与同级的局部变量|方法同名,不支持重载
2.实现
-
变量捕获
-
与匿名函数相比,效率会更高一筹。捕获局部变量的声明周期
-
如果匿名函数被转换成委托实例,委托可能要等到该返回许久之后再执行,因此
编译器需要将捕获的变量保存在一个类当中,然后让委托指向该类的一个方法
-
局部方法只能在宿主的内部调用,将捕获的变量保存在一个私有可变的结构体
-
捕获局部变量来自多个作用域时,会创建多个类。每一个类就代表一个作用域
static void Main(string[] args){ int n = 20; void Increment() => n++; } //编译后 private struct MainLocals { public int n; } static void Main(string[] args){ MainLocals locals = new MainLocals(); locals.n = 20; Increment(); } static void Increment(ref MainLocals locals) { locals.n++; }
-
out
int predicate;
int.TryParse("",out predicate); // C#7之前的写法
int.TryParse("",out int predicate) | int.TryParse("",out _);
default
default(T) //C#2.0引入的特性
// 返回该类型的默认值
泛型约束
static void IsRange<T>(T isTagret) where T : struct { }
static void IsRange<T>(T isTagret) where T : class { }
switch表达式
//原先:switch(value) 表达式:value switch
// =>宽箭头代替case关键字
// break|return被取消,因为每个模式的结果都是一个值|throw
// _代替了default
//类型模式
static String ShowName(Animal animal) => animal switch
{
Dog dog => dog.GetName(),
Cat cat => cat.GetName(),
Fox fox => fox.GetName(),
null => throw new ArgumentNullException(),
_ => throw new ArgumentException()
};
//元祖
static String ShowTuple(int x, int y) => (x, y) switch
{
(9, 10) => "优秀",
(7, 8) => "良好",
(5, 6) => "及格",
(_, 4) => "不及格"
};
//属性
static void LightColor(Light light)
{
Color color = light switch
{
{ Color: "红" } => Color.Red,
{ Color: "黄" } => Color.Yellow,
{ Color: "绿" } => Color.Green,
_ => throw new Exception()
};
}
//哨兵语句
static Type Infer(Object input) => input switch
{
int n when n > 0 => input.GetType(),
double d when d < 0 => input.GetType(),
String s when s.Length > 0 => input.GetType(),
_ => throw new InvalidCastException()
};