可空类型
概念
在一个类型后面加上问号”?”表示可空类型
例如 int? a 表示a可以是一个数字,也可以是null
转换
对于非空的情况,可以添加显式转换
代码语言:javascript复制int? a = 10;
int b = (int)a;
Console.WriteLine(b);
但是当a为null时会报错,因此需要加上if语句
代码语言:javascript复制int? a = null;
int b =
a == null
? -1
: (int)a;
Console.WriteLine(b);
//输出: -1
扩展方法
概念
扩展方法被定义在非泛型静态类中,扩展方法能够为现有的类添加新的方法,而无需定义新的类
示例
幂运算需要用到Math.Pow()函数,通过扩展方法,可以在int类型中添加Pow()方法,更快捷地计算幂
代码语言:javascript复制class Program
{
static void Main(string[] args)
{
int a = 2;
//计算2的10次方
Console.WriteLine(a.Pow(10));
Console.ReadKey();
}
}
public static class Extend
{
public static int Pow(this int num, int value)
{
return (int)Math.Pow(num, value);
}
}
序列化对象的二进制储存
通过将一个类序列化,可以用二进制的方式在硬盘上保存这个类
代码语言:javascript复制[Serializable]
class Struct
{
public int a = 10;
public string b = "123";
public Object c;
}
如果对象中出现对其它对象的引用,那么被引用的对象也会被写入硬盘里,在下次读取时仍然可用
代码语言:javascript复制static void Main(string[] args)
{
Struct s = new Struct()
{
a = 99,
b = "DearXuan",
c = new Struct()
};
//保存
using(FileStream fileStream1 = new FileStream(@"D:1.xuan",FileMode.OpenOrCreate))
{
BinaryFormatter binaryFormatter = new BinaryFormatter();
binaryFormatter.Serialize(fileStream1, s);
}
//读取
using (FileStream fileStream = new FileStream(@"D:1.xuan", FileMode.OpenOrCreate))
{
BinaryFormatter binaryFormatter = new BinaryFormatter();
Struct ss = binaryFormatter.Deserialize(fileStream) as Struct;
Console.WriteLine(ss.a);
Console.WriteLine(ss.b);
Console.WriteLine(((Struct)ss.c).a);
}
Console.ReadLine();
}
由于数据是二进制的形式储存,因此文件后缀名可以任意取
UWP的UI线程
UI线程
UI线程维护一个消息队列,所有的UI事件都会被送入消息队列中,在UI线程里执行。如果UI线程中存在耗时操作,就会导致消息得不到及时处理,程序无法响应输入,出现界面卡死
异步任务
使用async修饰方法,使之成为异步任务,用await修饰语句,使之成为等待任务
await修饰的代码将会在子线程中执行,并且不会有返回值
下面的代码生成了一个弹窗,使用await修饰ShowAsync(),使之不会阻塞UI线程
代码语言:javascript复制public async static void ShowOKDialog(string title, string content, Action onOkClick, Action onCloseClick)
{
ContentDialog dialog = new ContentDialog();
dialog.Title = title;
dialog.Content = content;
dialog.PrimaryButtonText = "好的";
dialog.CloseButtonText = "取消";
dialog.DefaultButton = ContentDialogButton.Primary;
if(onOkClick != null)
{
dialog.PrimaryButtonClick = (_s, _e) => { onOkClick(); };
}
if(onCloseClick != null)
{
dialog.CloseButtonClick = (_s, _e) => { onCloseClick(); };
}
await dialog.ShowAsync();
}
想要对用户的点击事件做出响应,只需要为“确定”和“取消”按钮添加点击事件即可
跨线程更新UI
使用以下代码将函数放在UI线程执行。如果涉及UI更新的函数在子线程中执行则会报错
代码语言:javascript复制public async static void Invoke(Action action, CoreDispatcherPriority Priority = CoreDispatcherPriority.Normal)
{
await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(Priority, () => { action(); });
}
默认参数
使用默认参数
直接在方法的参数里为变量赋值,其值会作为默认值传入
代码语言:javascript复制public static int add(int a = 5,int b = 10,int c = 15)
{
return a b c;
}
此时调用add(),会返回30
代码语言:javascript复制static void Main(string[] args)
{
Console.Write(add());
//结果: 30
Console.ReadLine();
}
覆盖默认参数
按顺序在add()中输入参数,默认参数将会被覆盖
代码语言:javascript复制static void Main(string[] args)
{
Console.Write(add(0,0));
//结果: 15
Console.ReadLine();
}
public static int add(int a = 5,int b = 10,int c = 15)
{
return a b c;
}
上面的代码在调用add()时输入了两个参数,但是add()有三个参数,因此前两个被覆盖了
如果希望不按顺序,只需要在参数前面加上变量名
代码语言:javascript复制static void Main(string[] args)
{
Console.Write(add(a: 0, c: 0));
//结果: 10
Console.ReadLine();
}
public static int add(int a = 5,int b = 10,int c = 15)
{
return a b c;
}
上面的代码指定了a和c的变量值为0,而b仍为默认值,因此输出结果10
自动释放资源
IDispose接口
在using语句中定义的对象,将会在脱离using语句后自动释放资源
IDispose接口提供了一种方法来让程序自动释放资源,你需要把释放资源的语句写在Dispose()函数中
代码语言:javascript复制class Program
{
static void Main(string[] args)
{
using(Example example = new Example())
{
Console.WriteLine("1");
}
// 运行结果:
// Create
// 1
// Dispose
}
}
class Example: IDisposable
{
public Example()
{
Console.WriteLine("Create");
}
public void Dispose()
{
Console.WriteLine("Dispose");
}
}
在读取文件时,将FileStream定义在using语句中,可以在执行完毕后自动释放,以免长时间占用
代码语言:javascript复制using(FileStream fileStream = new FileStream(@"D:1.xuan",FileMode.OpenOrCreate))
{
//读取文件
}
析构函数
析构函数与构造函数相反,析构函数在对象被gc释放时调用,因此你无法控制它被调用的具体时间
析构函数中不应该出现任何耗时操作或死循环,否则函数将会被系统强行中断
代码语言:javascript复制class Program
{
static void Main(string[] args)
{
Example example = new Example();
example = null;
}
// 运行结果:
// Create
// Dispose
}
class Example
{
public Example()
{
Console.WriteLine("Create");
}
~Example()
{
Console.WriteLine("Dispose");
}
}