mirror of
https://github.com/m-lamonaca/dev-notes.git
synced 2025-06-08 18:57:12 +00:00
merge main into NET-6
This commit is contained in:
commit
b33336d7c1
21 changed files with 299 additions and 178 deletions
|
@ -257,6 +257,80 @@ Project
|
|||
}
|
||||
```
|
||||
|
||||
## State Management
|
||||
|
||||
### Blazor WASM
|
||||
|
||||
```cs
|
||||
// setup state singleton
|
||||
builder.Services.AddSingleton<StateContainer>();
|
||||
```
|
||||
|
||||
```cs
|
||||
// StateContainer singleton
|
||||
using System;
|
||||
|
||||
public class StateContainer
|
||||
{
|
||||
private int _counter;
|
||||
|
||||
public string Property
|
||||
{
|
||||
get => _counter;
|
||||
set
|
||||
{
|
||||
_counter = value;
|
||||
NotifyStateChanged(); // will trigger StateHasChanged(), causing a render
|
||||
}
|
||||
}
|
||||
|
||||
public event Action OnChange;
|
||||
|
||||
private void NotifyStateChanged() => OnChange?.Invoke();
|
||||
}
|
||||
```
|
||||
|
||||
```cs
|
||||
// component that changes the state
|
||||
@inject StateContainer State
|
||||
|
||||
// Delegate event handlers automatically trigger a UI render
|
||||
<button @onClick="@HandleClick">
|
||||
Change State
|
||||
</button>
|
||||
|
||||
@code {
|
||||
private void HandleClick()
|
||||
{
|
||||
State.Property += 1; // update state
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
```cs
|
||||
// component that should be update on state change
|
||||
@implements IDisposable
|
||||
@inject StateContainer State
|
||||
|
||||
<p>Property: <b>@State.Property</b></p>
|
||||
|
||||
@code {
|
||||
|
||||
// StateHasChanged notifies the component that its state has changed.
|
||||
// When applicable, calling StateHasChanged causes the component to be rerendered.
|
||||
|
||||
protected override void OnInitialized()
|
||||
{
|
||||
State.OnChange += StateHasChanged;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
State.OnChange -= StateHasChanged;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Javascript/.NET Interop
|
||||
|
||||
[Call Javascript from .NET](https://docs.microsoft.com/en-us/aspnet/core/blazor/call-javascript-from-dotnet)
|
||||
|
|
127
DotNet/C#/C#.md
127
DotNet/C#/C#.md
|
@ -33,7 +33,7 @@ to native code later.
|
|||
```cs
|
||||
// comment
|
||||
/* multi line comment */
|
||||
// / single line xml comment (docstring)
|
||||
/// single line xml comment (docstring)
|
||||
/** multi line xml string (docsting) */
|
||||
```
|
||||
|
||||
|
@ -1219,16 +1219,6 @@ type OutMethod(type param1, out type param2){}
|
|||
OutMethod(arg1, out var arg2); // create out variable on the fly
|
||||
```
|
||||
|
||||
<!-- TODO: ### References to variables
|
||||
|
||||
**Constraints**:
|
||||
|
||||
```cs
|
||||
string _string = null; // init string object
|
||||
ref string referenceToString = ref _string; // referenceToString points to _string, it's a reference
|
||||
referenceToString = "value"; // data goes through referenceToString and into _string
|
||||
``` -->
|
||||
|
||||
### Returning Multiple Values with Tuples
|
||||
|
||||
**Must** be C# 7+.
|
||||
|
@ -2101,13 +2091,13 @@ Any method from any accessible class or struct that matches the delegate type ca
|
|||
This makes it possible to programmatically change method calls, and also plug new code into existing classes.
|
||||
|
||||
```cs
|
||||
// dedlegate definition
|
||||
public delegate Type DelegateName(Type param, ...); // can take any method with specidied type params and return type
|
||||
public delegate bool Predicate<in T>(T obj);
|
||||
// delegate definition
|
||||
public delegate Type Delegate(Type param, ...); // can take any method with specidied type params and return type
|
||||
public delegate Type Delegate<T>(T param); // generic delegate
|
||||
|
||||
// delegate creation
|
||||
var delegate = new Delegate<Type>(method); // explicit creation, useful when compiler cannot infer delegate type
|
||||
Delegate<Type> delegate = method; // implicit creation
|
||||
var delegate = new Delegate<Type>(Method); // explicit creation, useful when compiler cannot infer delegate type
|
||||
Delegate<Type> delegate = Method; // implicit creation
|
||||
```
|
||||
|
||||
### [Multicast Delegates](https://docs.microsoft.com/en-us/dotnet/api/system.multicastdelegate)
|
||||
|
@ -2115,9 +2105,9 @@ Delegate<Type> delegate = method; // implicit creation
|
|||
**Multicast Delegares** are delegates that can have more than one element in their invocation list.
|
||||
|
||||
```cs
|
||||
Delegate<Type> multicastDelegate = method1 + method2 + ...; // multicast delegate creation
|
||||
multicastDelegate += method; // add method to delegate
|
||||
multicastDelegate -= method; // remove method from delegate
|
||||
Delegate<Type> multicastDelegate = Method1 + Method2 + ...; // multicast delegate creation
|
||||
multicastDelegate += Method; // add method to delegate
|
||||
multicastDelegate -= Method; // remove method from delegate
|
||||
```
|
||||
|
||||
**NOTE**: Delegate removal behaves in a potentially surprising way if the delegate removed refers to multiple methods.
|
||||
|
@ -2129,7 +2119,7 @@ Invoking a delegate with a single target method works as though the code had cal
|
|||
Invoking a multicast delegate is just like calling each of its target methods in turn.
|
||||
|
||||
```cs
|
||||
Delegate<Type> delegate = method;
|
||||
Delegate<Type> delegate = Method;
|
||||
|
||||
delegate(args); // use delegat as standard method
|
||||
delegate.DynamicInvoke(argsArray); // Dynamically invokes the method represented by the current delegate.
|
||||
|
@ -2181,12 +2171,6 @@ var f = int (x) => x; // explicitly specifying the return type of an implicit i
|
|||
var f = static void (_) => Console.Write("Help");
|
||||
```
|
||||
|
||||
### Captured Variables
|
||||
|
||||
<!-- TODO: page 396 of Ian Griffiths - Programming C%23 8.0_Build Cloud, Web, and Desktop Applications -->
|
||||
|
||||
<!-- todo: static anonymous functions -->
|
||||
|
||||
---
|
||||
|
||||
## [Events](https://www.tutorialsteacher.com/csharp/csharp-event)
|
||||
|
@ -2197,10 +2181,11 @@ The class who raises events is called _Publisher_, and the class who receives th
|
|||
Typically, a publisher raises an event when some action occurred. The subscribers, who are interested in getting a notification when an action occurred, should register with an event and handle it.
|
||||
|
||||
```cs
|
||||
public delegate void EventDelegate(object sender, CustomEventArgs args); // called on event trigger
|
||||
|
||||
public class Publisher
|
||||
{
|
||||
|
||||
public event Delegate<Type> Event;
|
||||
public event EventDelegate Event;
|
||||
|
||||
// A derived class should always call the On<EventName> method of the base class to ensure that registered delegates receive the event.
|
||||
public virtual void OnEvent(Type param)
|
||||
|
@ -2215,19 +2200,15 @@ public class Publisher
|
|||
```cs
|
||||
public class Subscriber
|
||||
{
|
||||
|
||||
Publisher publisher = new Publisher();
|
||||
|
||||
public Subscriber()
|
||||
{
|
||||
publisher.Event += eh_Event; // register handler (+= syntax)
|
||||
publisher.OnEvent += Handler; // register handler (+= syntax)
|
||||
}
|
||||
|
||||
// event handler, handles the event because it matches the signature of the Event delegate.
|
||||
public Delegate<Type> eh_Event()
|
||||
{
|
||||
// act
|
||||
}
|
||||
// event handler, matches the signature of the Event delegate.
|
||||
public Type Handler() { /* act */ }
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -2254,22 +2235,17 @@ public class Subsciber
|
|||
|
||||
public Subscriber()
|
||||
{
|
||||
publisher.Event += eh_Event; // register handler (+= syntax)
|
||||
publisher.OnEvent += Handler; // register handler (+= syntax)
|
||||
}
|
||||
|
||||
public void eh_Event(object sender, EventArgs e)
|
||||
{
|
||||
// act
|
||||
}
|
||||
public Type Handler(object sender, EventArgs e) { /* act */ }
|
||||
}
|
||||
```
|
||||
|
||||
### Custom Event Args
|
||||
|
||||
```cs
|
||||
public class CustomEventArgs : EventArgs {
|
||||
// custom attributes
|
||||
}
|
||||
public class CustomEventArgs : EventArgs { }
|
||||
|
||||
public class Publisher
|
||||
{
|
||||
|
@ -2287,13 +2263,10 @@ public class Subsciber
|
|||
|
||||
public Subscriber()
|
||||
{
|
||||
publisher.Event += eh_Event; // register handler (+= syntax)
|
||||
publisher.OnEvent += Handler; // register handler (+= syntax)
|
||||
}
|
||||
|
||||
public void eh_Event(object sender, CustomEventArgs e)
|
||||
{
|
||||
// act
|
||||
}
|
||||
public Type Handler(object sender, CustomEventArgs e) { /* act */ }
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -2900,6 +2873,53 @@ n << m
|
|||
n * 2^m
|
||||
```
|
||||
|
||||
## Unsafe Code & Pointers
|
||||
|
||||
The `unsafe` keyword denotes an *unsafe context*, which is required for any operation involving pointers.
|
||||
|
||||
In an unsafe context, several constructs are available for operating on pointers:
|
||||
|
||||
- The `*` operator may be used to perform pointer indirection ([Pointer indirection][ptr_indirection]).
|
||||
- The `->` operator may be used to access a member of a struct through a pointer ([Pointer member access][ptr_member_acces]).
|
||||
- The `[]` operator may be used to index a pointer ([Pointer element access][ptr_elem_access]).
|
||||
- The `&` operator may be used to obtain the address of a variable ([The address-of operator][ptr_addr_of]).
|
||||
- The `++` and `--` operators may be used to increment and decrement pointers ([Pointer increment and decrement][ptr_incr_decr]).
|
||||
- The `+` and `-` operators may be used to perform pointer arithmetic ([Pointer arithmetic][ptr_math]).
|
||||
- The `==`, `!=`, `<`, `>`, `<=`, and `>=` operators may be used to compare pointers ([Pointer comparison][ptr_comparison]).
|
||||
- The `stackalloc` operator may be used to allocate memory from the call stack ([Stack allocation][stack_alloc]).
|
||||
|
||||
The `fixed` statement prevents the garbage collector from relocating a movable variable. It's only permitted in an unsafe context.
|
||||
It's also possible to use the fixed keyword to create fixed size buffers.
|
||||
|
||||
The `fixed` statement sets a pointer to a managed variable and "pins" that variable during the execution of the statement.
|
||||
Pointers to movable managed variables are useful only in a fixed context. Without a fixed context, garbage collection could relocate the variables unpredictably.
|
||||
The C# compiler only allows to assign a pointer to a managed variable in a fixed statement.
|
||||
|
||||
```cs
|
||||
unsafe Type UnsafeMethod() { /* unasfe context */ }
|
||||
// or
|
||||
unsafe
|
||||
{
|
||||
// Using fixed allows the address of pt members to be taken,
|
||||
// and "pins" pt so that it is not relocated.
|
||||
Point pt = new Point();
|
||||
fixed (int* p = &pt.x)
|
||||
{
|
||||
*p = 1;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
[ptr_indirection]: (https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/language-specification/unsafe-code#pointer-indirection)
|
||||
[ptr_member_acces]: (https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/language-specification/unsafe-code#pointer-member-access)
|
||||
[ptr_elem_access]: (https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/language-specification/unsafe-code#pointer-element-access)
|
||||
[ptr_addr_of]: (https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/language-specification/unsafe-code#the-address-of-operator)
|
||||
[ptr_incr_decr]: (https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/language-specification/unsafe-code#pointer-increment-and-decrement)
|
||||
[ptr_math]: (https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/language-specification/unsafe-code#pointer-arithmetic)
|
||||
[ptr_comparison]: (https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/language-specification/unsafe-code#pointer-comparison)
|
||||
[stack_alloc]: (https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/language-specification/unsafe-code#stack-allocation)
|
||||
[fixed_buffers]: (https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/language-specification/unsafe-code#fixed-size-buffers)
|
||||
|
||||
### Native Memory
|
||||
|
||||
```cs
|
||||
|
@ -2912,3 +2932,14 @@ unsafe
|
|||
NativeMemory.Free(buffer);
|
||||
}
|
||||
```
|
||||
|
||||
### DllImport & Extern
|
||||
|
||||
The `extern` modifier is used to declare a method that is implemented externally.
|
||||
A common use of the extern modifier is with the `DllImport` attribute when using Interop services to call into *unmanaged* code.
|
||||
In this case, the method must also be declared as `static`.
|
||||
|
||||
```cs
|
||||
[DllImport("avifil32.dll")]
|
||||
private static extern void AVIFileInit();
|
||||
```
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# Reactive Extensions (Rx)
|
||||
|
||||
The **Reactive Extensions** for .NET, or **Rx**, are designed for working with asynchro‐nous and event-based sources of information.
|
||||
The **Reactive Extensions** for .NET, or **Rx**, are designed for working with asynchronous and event-based sources of information.
|
||||
Rx provides services that help orchestrate and synchronize the way code reacts to data from these kinds of sources.
|
||||
|
||||
Rx’s fundamental abstraction, `IObservable<T>`, represents a sequence of items, and its operators are defined as extension methods for this interface.
|
||||
|
@ -14,8 +14,8 @@ Because Rx implements standard LINQ operators, it's possible to write queries ag
|
|||
|
||||
## Foundamental Interfaces
|
||||
|
||||
The two most important types in Rx are the `IObservable<T>` and `IObserver<T>` interfaces. They are important enough to be in the System namespace.
|
||||
The other parts of Rx are in the `System.Reactive` NuGet package.
|
||||
The two most important types in Rx are the `IObservable<T>` and `IObserver<T>` interfaces.
|
||||
They are important enough to be in the System namespace. The other parts of Rx are in the `System.Reactive` NuGet package.
|
||||
|
||||
```cs
|
||||
public interface IObservable<out T>
|
||||
|
@ -31,7 +31,8 @@ public interface IObserver<in T>
|
|||
}
|
||||
```
|
||||
|
||||
The fundamental abstraction in Rx, `IObservable<T>`, is implemented by *event sources*. Instead of using the `event` keyword, it models events as a *sequence of items*. An `IObservable<T>` provides items to subscribers as and when it’s ready to.
|
||||
The fundamental abstraction in Rx, `IObservable<T>`, is implemented by *event sources*. Instead of using the `event` keyword, it models events as a *sequence of items*.
|
||||
An `IObservable<T>` provides items to subscribers as and when it’s ready to do so.
|
||||
|
||||
It's possible to subscribe to a source by passing an implementation of `IObserver<T>` to the `Subscribe` method.
|
||||
The source will invoke `OnNext` when it wants to report events, and it can call `OnCompleted` to indicate that there will be no further activity.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue