[十月的寒流]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
image

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;
		}				
	}
}
posted @ 2024-02-17 01:17  Senya  阅读(322)  评论(0)    收藏  举报