[十月的寒流]C#视频学习笔记1
C#的一些冷知识(其一)
1.函数参数的传递方式
默认函数传递参数的方式是位置参数,也就是按照参数的声明顺序依次填入,其他还有命名参数的传递方式,如下:
Foo("Tom",18,true);
Foo("Tom",alive:false);
//在C#7.2以后可以在命名参数后继续使用位置参数
Foo("Tom",age:11,true);
void Foo(string name, int age = 12, bool alive = true)
{
new { name, age, alive}.Dump();
}
2.枚举类型的继承
枚举类型可以继承某些类型,以使得所有元素的类型不再是默认的int

3.接口的显式实现
显式实现接口主要用于禁止直接调用某个继承的方法,错误会直接在编译的提示。甚至转换类型进行调用也可以使用抛出异常的方式禁止调用。
var mc = new MyClass();
mc.Foo();//编译器会提示没有这个方法
((IFoo)mc).Foo();//需要转成接口类型才能调用
((IFoo)mc).Add();//这里即使调用了,也会抛出异常
class MyClass : IFoo
{
void IFoo.Foo()
{
"Inside Foo method".Dump();
}
void IFoo.Add()
{
throw new NotSupportedException();
}
}
interface IFoo
{
void Foo();
void Add();
}
4.await可以等待的类型
await除了可以等待Task或者ValueTask,还可以对任何一个提供了GetAwaiter方法进行await操作。
var md = new MyDelay(2);
await md;
"finish".Dump();
class MyDelay
{
int secs;
public MyDelay(int secs)
{
this.secs = secs;
}
public TaskAwaiter GetAwaiter()
{
return Task.Delay(TimeSpan.FromSeconds(secs)).GetAwaiter();
}
}
还可以使用扩展方法
var md = new MyDelay(2);
await md;
"使用MyDelay的GetAwaiter".Dump();
await TimeSpan.FromSeconds(1.5);
"使用TimeSpan的GetAwaiter".Dump();
await 3;
"使用int的GetAwaiter".Dump();
class MyDelay
{
public int secs {get;private set;}
public MyDelay(int secs)
{
this.secs = secs;
}
}
static class MyExtensions
{
public static TaskAwaiter GetAwaiter(this MyDelay md)
{
return Task.Delay(TimeSpan.FromSeconds(md.secs)).GetAwaiter();
}
public static TaskAwaiter GetAwaiter(this TimeSpan ts)
{
return Task.Delay(ts).GetAwaiter();
}
public static TaskAwaiter GetAwaiter(this int seconds)
{
return Task.Delay(TimeSpan.FromSeconds(seconds)).GetAwaiter();
}
}
5.foreach的使用
foreach除了可以遍历继承了IEnumerator的对象,还可以对其他有GetEnumerator方法的对象进行遍历。
var mc = new MyClass();
foreach (var x in mc)
{
x.Dump();
}
//使用扩展方法中int的GetEnumerator可以直接foreach 5
foreach(var n in 5)
{
n.Dump();
}
//是否实现IEnumerable都可以,只要提供了public IEnumerator GetEnumerator()方法即可进行foreach
class MyClass : IEnumerable
{
public IEnumerator GetEnumerator()
{
for(int i = 0; i < 5; i++)
{
yield return i.ToString();
}
}
}
static class MyExtensions
{
public static IEnumerator GetEnumerator(this int c)
{
for (int i = 0; i < 5; i++)
{
yield return i.ToString();
}
}
}
6.IAsyncEnumerable的遍历
var mc = new MyClass();
await foreach (var x in mc)
{
x.Dump();//遍历时每隔0.2s会打印一次
}
//IAsyncEnumerable<int>可以不实现,只要提供了public IAsyncEnumerator<int> GetAsyncEnumerator方法
class MyClass : IAsyncEnumerable<int>
{
public async IAsyncEnumerator<int> GetAsyncEnumerator(CancellationToken cancellationToken = default)
{
for (int i = 0; i < 5; i++)
{
await Task.Delay(200);
yield return i;
}
}
}
浙公网安备 33010602011771号