No conocer los detalles de C #

Original: Usted no sabe los detalles en C #

Prefacio #

Hay una cosa que se llama tipo de pato, el llamado duck typing es que mientras las cosas se comportan como un pato a continuación, ser capaz de lanzar esta cosa es un pato.

C # es en realidad oculta dentro de una gran cantidad de tipos similares de patos, pero muchos desarrolladores no conocen y, por lo tanto, no puede hacer uso de estas cosas, así que hoy estoy escondido en el desglose de lo que estos compiladores en detalle.

No solo Tasky ValueTaskal await#

Al escribir un código asíncrono en C #, a menudo elegimos un código asíncrono está contenida en uno Tasko ValueTask, la persona que llama será capaz de utilizar esta awaitforma de lograr una llamada asincrónica.

Xika Xi, no es la única Tasky ValueTaskla capacidad await. TaskY ValueTaskdetrás del grupo de subprocesos es, obviamente, involucrado en la programación, pero ¿por qué el C # async/ awaitse dice que es coroutineél?

Debido a que awaitno son necesariamente cosas Task/ ValueTask, en C # siempre y cuando su clase contiene GetAwaiter()métodos y bool IsCompletedpropiedades, y GetAwaiter()las cosas volvieron contiene un GetResult()método, una bool IsCompletedpropiedad e implementado INotifyCompletion, el objeto de esta clase es que pueda awaitde.

Por lo tanto, en las operaciones de paquete de E / S, podemos lograr un auto Awaiter, que se basa en el subyacente epoll/ IOCPaplicación, de manera que cuando awaitel tiempo no crea ningún hilo, también sin ningún tipo de programación de subprocesos, pero a directamente el control. El sistema operativo después de la finalización de E / S llamando al CompletionPort(Windows), etc., para informar al modo de usuario para completar una llamada asincrónica, a continuación, reanudar el contexto continúan con la lógica restante, que es en realidad una verdadera stackless coroutine.

 
 
Copiar
public class MyTask<T> { public MyAwaiter<T> GetAwaiter() { return new MyAwaiter<T>(); } } public class MyAwaiter<T> : INotifyCompletion { public bool IsCompleted { get; private set; } public T GetResult() { throw new NotImplementedException(); } public void OnCompleted(Action continuation) { throw new NotImplementedException(); } } public class Program { static async Task Main(string[] args) { var obj = new MyTask<int>(); await obj; } }

De hecho, el .NET Core E / S asociada con la API asíncrona está haciendo de hecho es así, el proceso de operación de E / S no tendrá ningún hilo de la espera de los resultados de la asignación están coroutinefuncionando: las operaciones de E / S directa comienzan dejar fuera de control hasta que la operación de E / S se ha completado. La razón por la que a veces se encuentra awaitantes y después de que el mensaje ha cambiado, es sólo porque Tasksí está previsto.

UWP utilizado en el desarrollo de IAsyncAction/ IAsyncOperation<T>es de la parte inferior del envase, y Taskno tiene nada que hacer, pero lata await, y si el C ++ / WinRT uwp desarrollo luego regresar estas interfaces son también posibles métodos co_awaitde.

No solo IEnumerabley IEnumeratorcon el fin de ser foreach#

menudo vamos a escribir el siguiente código:

 
 
Copiar
foreach (var i in list) { // ...... }

Entonces uno puede preguntarse por qué foreach, porque la mayoría de ellos responderá que listlos implementos IEnumerableo IEnumerator.

Pero, de hecho, si usted quiere ser un objeto foreach, sólo se necesita proporcionar un GetEnumerator()método y el GetEnumerator()objeto devuelto contiene una bool MoveNext()añadir un método Currentatributo.

 
 
Copiar
class MyEnumerator<T> { public T Current { get; private set; } public bool MoveNext() { throw new NotImplementedException(); } } class MyEnumerable<T> { public MyEnumerator<T> GetEnumerator() { throw new NotImplementedException(); } } class Program { public static void Main() { var x = new MyEnumerable<int>(); foreach (var i in x) { // ...... } } }

No solo IAsyncEnumerabley IAsyncEnumeratorcon el fin de ser await foreach#

Como el anterior, pero esta vez los requisitos han cambiado, GetEnumerator()y MoveNext()cambiado GetAsyncEnumerator()y MoveNextAsync().

En el que MoveNextAsync()las cosas deberían ser un retorno Awaitable<bool>, ya que esto Awaitablelo que al final es que puede ser Task/ ValueTaskpuede ser otra o en la propia aplicación.

 
 
Copiar
class MyAsyncEnumerator<T> { public T Current { get; private set; } public MyTask<bool> MoveNextAsync() { throw new NotImplementedException(); } } class MyAsyncEnumerable<T> { public MyAsyncEnumerator<T> GetAsyncEnumerator() { throw new NotImplementedException(); } } class Program { public static async Task Main() { var x = new MyAsyncEnumerable<int>(); await foreach (var i in x) { // ...... } } }

ref struct¿Cómo lograr IDisposable#

Como todos sabemos ref struct, ya que es necesario y no se pueden encajonar en la pila, no se puede implementar la interfaz, pero si usted ref structtiene una void Dispose()para que pueda ser utilizado usingpara lograr la sintaxis objeto se destruye automáticamente.

 
 
Copiar
ref struct MyDisposable { public void Dispose() => throw new NotImplementedException(); } class Program { public static void Main() { using var y = new MyDisposable(); // ...... } }

No sólo Rangese puede utilizar rebanadas #

C # 8 introduce Ranges, permitiendo que la operación de corte, pero en realidad no es necesario proporcionar un receptor Rangeindexador puede escribir parámetros para utilizar esta característica.

Mientras que su clase puede ser contado (propiedad Lengtho Countatributos), y puede ser en rodajas (para tener un Slice(int, int)método), a continuación, puede utilizar esta función.

 
 
Copiar
class MyRange { public int Count { get; private set; } public object Slice(int x, int y) => throw new NotImplementedException(); } class Program { public static void Main() { var x = new MyRange(); var y = x[1..]; } }

No sólo Indexse puede utilizar el índice #

C # 8 índices para la introducción del índice, tales como el uso ^1del elemento de índice penúltima, pero en realidad no es necesario proporcionar un recibir Indexindexador puede escribir parámetros para utilizar esta característica.

Mientras que su clase puede ser contado (propiedad Lengtho Countatributos) y puede ser indexado (tiene un receptor intparámetros indexador), a continuación, puede utilizar esta función.

 
 
Copiar
class MyIndex { public int Count { get; private set; } public object this[int index] { get => throw new NotImplementedException(); } } class Program { public static void Main() { var x = new MyIndex(); var y = x[^1]; } }

Para lograr el tipo de deconstrucción #

¿Cómo lograr un tipo de deconstrucción de la misma? De hecho, acaba de escribir un nombre para Deconstruct()el método y los parámetros son outpuede ser.

 
 
Copiar
class MyDeconstruct { private int A => 1; private int B => 2; public void Deconstruct(out int a, out int b) { a = A; b = B; } } class Program { public static void Main() { var x = new MyDeconstruct(); var (o, u) = x; } }

No sólo se dio cuenta IEnumerablecon el fin de utilizar LINQ#

LINQ C # se utiliza comúnmente en un lenguaje de consulta integrado le permite escribir código como este:

 
 
Copiar
from c in list where c.Id > 5 select c;

Sin embargo, en el código anterior listtipos no necesariamente tiene que darse cuenta IEnumerable, de hecho, siempre y cuando no es un nombre correspondiente métodos de extensión puede ser, por ejemplo, ha llamado el Selectmétodo puede ser utilizado select, con los conocidos Wheremétodos se pueden utilizar where.

 
 
Copiar
class Just<T> : Maybe<T> { private readonly T value; public Just(T value) { this.value = value; } public override Maybe<U> Select<U>(Func<T, Maybe<U>> f) => f(value); public override string ToString() => $"Just {value}"; } class Nothing<T> : Maybe<T> { public override Maybe<U> Select<U>(Func<T, Maybe<U>> _) => new Nothing<U>(); public override string ToString() => "Nothing"; } abstract class Maybe<T> { public abstract Maybe<U> Select<U>(Func<T, Maybe<U>> f); public Maybe<V> SelectMany<U, V>(Func<T, Maybe<U>> k, Func<T, U, V> s) => Select(x => k(x).Select(y => new Just<V>(s(x, y)))); public Maybe<U> Where(Func<Maybe<T>, bool> f) => f(this) ? this : new Nothing<T>(); } class Program { public static void Main() { var x = new Just<int>(3); var y = new Just<int>(7); var z = new Nothing<int>(); var u = from x0 in x from y0 in y select x0 + y0; var v = from x0 in x from z0 in z select x0 + z0; var just = from c in x where true select c; var nothing = from c in x where false select c; } }

Supongo que te gusta

Origin www.cnblogs.com/lonelyxmas/p/12630097.html
Recomendado
Clasificación