mirror of
https://github.com/m-lamonaca/dev-notes.git
synced 2025-06-08 10:47:13 +00:00
remove mkdocs specific syntax
This commit is contained in:
parent
8d08c1964f
commit
8026e1465b
77 changed files with 1128 additions and 1128 deletions
|
@ -18,7 +18,7 @@ The component class is usually written in the form of a Razor markup page with a
|
|||
|
||||
[Blazor Components](https://docs.microsoft.com/en-us/aspnet/core/blazor/components/)
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
@page "/route/{RouteParameter}" // make component accessible from a URL
|
||||
@page "/route/{RouteParameter?}" // specify route parameter as optional
|
||||
@page "/route/{RouteParameter:<type>}" // specify route parameter type
|
||||
|
@ -59,7 +59,7 @@ The component class is usually written in the form of a Razor markup page with a
|
|||
|
||||
It's now possible to pass state when navigating in Blazor apps using the `NavigationManager`.
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
navigationManager.NavigateTo("/<route>", new NavigationOptions { HistoryEntryState = value });
|
||||
```
|
||||
|
||||
|
@ -67,12 +67,12 @@ This mechanism allows for simple communication between different pages. The spec
|
|||
|
||||
### Blazor WASM
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
// setup state singleton
|
||||
builder.Services.AddSingleton<StateContainer>();
|
||||
```
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
// StateContainer singleton
|
||||
using System;
|
||||
|
||||
|
@ -96,7 +96,7 @@ public class StateContainer
|
|||
}
|
||||
```
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
// component that changes the state
|
||||
@inject StateContainer State
|
||||
|
||||
|
@ -113,7 +113,7 @@ public class StateContainer
|
|||
}
|
||||
```
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
// component that should be update on state change
|
||||
@implements IDisposable
|
||||
@inject StateContainer State
|
||||
|
@ -139,7 +139,7 @@ public class StateContainer
|
|||
|
||||
## Data Binding & Events
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
<p>
|
||||
<button @on{DOM EVENT}="{DELEGATE}" />
|
||||
<button @on{DOM EVENT}="{DELEGATE}" @on{DOM EVENT}:preventDefault /> // prevent default action
|
||||
|
@ -198,7 +198,7 @@ public class StateContainer
|
|||
|
||||
To render a Blazor component from JavaScript, first register it as a root component for JavaScript rendering and assign it an identifier:
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
// Blazor Server
|
||||
builder.Services.AddServerSideBlazor(options =>
|
||||
{
|
||||
|
@ -211,7 +211,7 @@ builder.RootComponents.RegisterForJavaScript<Counter>(identifier: "counter");
|
|||
|
||||
Load Blazor into the JavaScript app (`blazor.server.js` or `blazor.webassembly.js`) and then render the component from JavaScript into a container element using the registered identifier, passing component parameters as needed:
|
||||
|
||||
```js linenums="1"
|
||||
```js
|
||||
let containerElement = document.getElementById('my-counter');
|
||||
await Blazor.rootComponents.add(containerElement, 'counter', { incrementAmount: 10 });
|
||||
```
|
||||
|
@ -223,6 +223,6 @@ Custom elements use standard HTML interfaces to implement custom HTML elements.
|
|||
|
||||
To create a custom element using Blazor, register a Blazor root component as custom elements like this:
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
options.RootComponents.RegisterAsCustomElement<Counter>("my-counter");
|
||||
```
|
||||
|
|
|
@ -33,7 +33,7 @@ Short-circuiting is often desirable because it avoids unnecessary work.
|
|||
|
||||
It's possible to perform actions both *before* and *after* the next delegate:
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
// "inline" middleware, best if in own class
|
||||
app.Use(async (context, next) =>
|
||||
{
|
||||
|
@ -45,7 +45,7 @@ app.Use(async (context, next) =>
|
|||
|
||||
`Run` delegates don't receive a next parameter. The first `Run` delegate is always terminal and terminates the pipeline.
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
// "inline" middleware, best if in own class
|
||||
app.Use(async (context, next) =>
|
||||
{
|
||||
|
@ -69,7 +69,7 @@ The Endpoint middleware executes the filter pipeline for the corresponding app t
|
|||
|
||||
The order that middleware components are added in the `Startup.Configure` method defines the order in which the middleware components are invoked on requests and the reverse order for the response. The order is **critical** for security, performance, and functionality.
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
if (env.IsDevelopment())
|
||||
{
|
||||
app.UseDeveloperExceptionPage();
|
||||
|
@ -121,7 +121,7 @@ Unlike with `MapWhen`, this branch is rejoined to the main pipeline if it doesn'
|
|||
|
||||
Middleware is generally encapsulated in a class and exposed with an extension method.
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
public class CustomMiddleware
|
||||
{
|
||||
private readonly RequestDelegate _next;
|
||||
|
@ -152,7 +152,7 @@ The middleware class **must** include:
|
|||
|
||||
## Middleware Extension Methods
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
|
||||
public static class MiddlewareExtensions
|
||||
|
@ -164,7 +164,7 @@ public static class MiddlewareExtensions
|
|||
}
|
||||
```
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
// other middlewares
|
||||
|
||||
app.UseCustom(); // add custom middleware in the pipeline
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
> **Note**: Requires .NET 6+
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
var builder = WebApplication.CreateBuilder(args);
|
||||
|
||||
builder.Services.AddSingleton<IService, Service>();
|
||||
|
@ -41,7 +41,7 @@ Setting a value is done with `dotnet user-secrets set <key> <value>`, keys can b
|
|||
|
||||
## Swagger
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
builder.Services.AddEndpointsApiExplorer();
|
||||
builder.Services.AddSwaggerGen();
|
||||
|
||||
|
@ -59,7 +59,7 @@ app.MapPost("/route", Handler).Accepts<Type>(contentType);
|
|||
|
||||
## MVC
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
builder.Services.AddControllersWithViews();
|
||||
//or
|
||||
builder.Services.AddControllers();
|
||||
|
@ -95,7 +95,7 @@ app.MapControllerRoute(
|
|||
|
||||
To define routes and handlers using Minimal APIs, use the `Map(Get|Post|Put|Delete)` methods.
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
// the dependencies are passed as parameters in the handler delegate
|
||||
app.MapGet("/route/{id}", (IService service, int id) => {
|
||||
|
||||
|
@ -112,7 +112,7 @@ IResult Search(int id, int? page = 1, int? pageSize = 10) { /* ... */ }
|
|||
The `MapGroup()` extension method, which helps organize groups of endpoints with a common prefix.
|
||||
It allows for customizing entire groups of endpoints with a singe call to methods like `RequireAuthorization()` and `WithMetadata()`.
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
var group = app.MapGroup("<route-prefix>");
|
||||
|
||||
group.MapGet("/", GetAllTodos); // route: /<route-prefix>
|
||||
|
@ -126,14 +126,14 @@ group.MapGet("/{id}", GetTodo); // route: /<route-prefix>/{id}
|
|||
The `Microsoft.AspNetCore.Http.TypedResults` static class is the “typed” equivalent of the existing `Microsoft.AspNetCore.Http.Results` class.
|
||||
It's possible to use `TypedResults` in minimal APIs to create instances of the in-framework `IResult`-implementing types and preserve the concrete type information.
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
public static async Task<IResult> GetAllTodos(TodoDb db)
|
||||
{
|
||||
return TypedResults.Ok(await db.Todos.ToArrayAsync());
|
||||
}
|
||||
```
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
[Fact]
|
||||
public async Task GetAllTodos_ReturnsOkOfObjectResult()
|
||||
{
|
||||
|
@ -152,7 +152,7 @@ public async Task GetAllTodos_ReturnsOkOfObjectResult()
|
|||
|
||||
The `Results<TResult1, TResult2, TResultN>` generic union types, along with the `TypesResults` class, can be used to declare that a route handler returns multiple `IResult`-implementing concrete types.
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
// Declare that the lambda returns multiple IResult types
|
||||
app.MapGet("/todos/{id}", async Results<Ok<Todo>, NotFound> (int id, TodoDb db)
|
||||
{
|
||||
|
@ -164,7 +164,7 @@ app.MapGet("/todos/{id}", async Results<Ok<Todo>, NotFound> (int id, TodoDb db)
|
|||
|
||||
## Filters
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
public class ExampleFilter : IRouteHandlerFilter
|
||||
{
|
||||
public async ValueTask<object?> InvokeAsync(RouteHandlerInvocationContext context, RouteHandlerFilterDelegate next)
|
||||
|
@ -177,7 +177,7 @@ public class ExampleFilter : IRouteHandlerFilter
|
|||
}
|
||||
```
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
app.MapPost("/route", Handler).AddFilter<ExampleFilter>();
|
||||
```
|
||||
|
||||
|
@ -191,7 +191,7 @@ With Minimal APIs it's possible to access the contextual information by passing
|
|||
- `ClaimsPrincipal`
|
||||
- `CancellationToken` (RequestAborted)
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
app.MapGet("/hello", (ClaimsPrincipal user) => {
|
||||
return "Hello " + user.FindFirstValue("sub");
|
||||
});
|
||||
|
@ -201,7 +201,7 @@ app.MapGet("/hello", (ClaimsPrincipal user) => {
|
|||
|
||||
The `Microsoft.AspNetCore.OpenApi` package exposes a `WithOpenApi` extension method that generates an `OpenApiOperation` derived from a given endpoint’s route handler and metadata.
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
app.MapGet("/todos/{id}", (int id) => ...)
|
||||
.WithOpenApi();
|
||||
|
||||
|
@ -217,7 +217,7 @@ app.MapGet("/todos/{id}", (int id) => ...)
|
|||
Using [Minimal Validation](https://github.com/DamianEdwards/MinimalValidation) by Damian Edwards.
|
||||
Alternatively it's possible to use [Fluent Validation](https://fluentvalidation.net/).
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
app.MapPost("/widgets", (Widget widget) => {
|
||||
var isValid = MinimalValidation.TryValidate(widget, out var errors);
|
||||
|
||||
|
@ -240,7 +240,7 @@ class Widget
|
|||
|
||||
## JSON Serialization
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
// Microsoft.AspNetCore.Http.Json.JsonOptions
|
||||
builder.Services.Configure<JsonOptions>(opt =>
|
||||
{
|
||||
|
@ -250,7 +250,7 @@ builder.Services.Configure<JsonOptions>(opt =>
|
|||
|
||||
## Authorization
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddJwtBearer();
|
||||
|
||||
builder.Services.AddAuthorization();
|
||||
|
@ -283,13 +283,13 @@ app.MapGet("/special-secret", () => "This is a special secret!")
|
|||
The `user-jwts` tool is similar in concept to the existing `user-secrets` tools, in that it can be used to manage values for the app that are only valid for the current user (the developer) on the current machine.
|
||||
In fact, the `user-jwts` tool utilizes the `user-secrets` infrastructure to manage the key that the JWTs will be signed with, ensuring it’s stored safely in the user profile.
|
||||
|
||||
```sh linenums="1"
|
||||
```sh
|
||||
dotnet user-jwts create # configure a dev JWT fot the current user
|
||||
```
|
||||
|
||||
## Output Caching
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
builder.Services.AddOutputCaching(); // no special options
|
||||
builder.Services.AddOutputCaching(options =>
|
||||
{
|
||||
|
@ -321,7 +321,7 @@ app.MapGet("/<route>", [OutputCache(/* options */)]RouteHandler);
|
|||
|
||||
### Cache Eviction
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
|
||||
app.MapGet("/<route-one>", RouteHandler).CacheOutput(x => x.Tag("<tag>")); // tag cache portion
|
||||
|
||||
|
@ -333,11 +333,11 @@ app.MapGet("/<route-two>", (IOutputCacheStore cache, CancellationToken token) =>
|
|||
|
||||
### Custom Cache Policy
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
app.MapGet("/<route-one>", RouteHandler).CacheOutput(x => x.AddCachePolicy<CustomCachePolicy>());
|
||||
```
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
class CustomCachePolicy : IOutputCachePolicy
|
||||
{
|
||||
public ValueTask CacheRequestAsync(OutputCacheContext context, CancellationToken cancellationToken) { }
|
||||
|
@ -352,7 +352,7 @@ class CustomCachePolicy : IOutputCachePolicy
|
|||
|
||||
The *options pattern* uses classes to provide strongly-typed access to groups of related settings.
|
||||
|
||||
```json linenums="1"
|
||||
```json
|
||||
{
|
||||
"SecretKey": "Secret key value",
|
||||
"TransientFaultHandlingOptions": {
|
||||
|
@ -369,7 +369,7 @@ The *options pattern* uses classes to provide strongly-typed access to groups of
|
|||
}
|
||||
```
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
// options model for binding
|
||||
public class TransientFaultHandlingOptions
|
||||
{
|
||||
|
@ -378,13 +378,13 @@ public class TransientFaultHandlingOptions
|
|||
}
|
||||
```
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
// setup the options
|
||||
builder.Services.Configure<TransientFaultHandlingOptions>(builder.Configuration.GetSection<TransientFaultHandlingOptions>(nameof(Options)));
|
||||
builder.Services.Configure<TransientFaultHandlingOptions>(builder.Configuration.GetSection<TransientFaultHandlingOptions>(key));
|
||||
```
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
class DependsOnOptions
|
||||
{
|
||||
private readonly IOptions<TransientFaultHandlingOptions> _options;
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
## Markup
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
@page // set this as razor page
|
||||
|
||||
@model <App>.Models.Entity // if MVC set type of elements passed to the view
|
||||
|
@ -35,7 +35,7 @@
|
|||
|
||||
Example:
|
||||
|
||||
```html linenums="1"
|
||||
```html
|
||||
<!-- tag helpers for a lin in ASP.NET MVC -->
|
||||
<a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Index">Home</a>
|
||||
```
|
||||
|
@ -44,7 +44,7 @@ Example:
|
|||
|
||||
The `@addTagHelper` directive makes Tag Helpers available to the view. Generally, the view file is `Pages/_ViewImports.cshtml`, which by default is inherited by all files in the `Pages` folder and subfolders, making Tag Helpers available.
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
@using <App>
|
||||
@namespace <App>.Pages // or <Project>.Models
|
||||
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
|
||||
|
@ -57,7 +57,7 @@ The first parameter after `@addTagHelper` specifies the Tag Helpers to load (`*`
|
|||
|
||||
It's possible to disable a Tag Helper at the element level with the Tag Helper opt-out character (`!`)
|
||||
|
||||
```cshtml linenums="1"
|
||||
```cshtml
|
||||
<!-- disable email validation -->
|
||||
<!span asp-validation-for="Email" ></!span>
|
||||
```
|
||||
|
@ -66,7 +66,7 @@ It's possible to disable a Tag Helper at the element level with the Tag Helper o
|
|||
|
||||
The `@tagHelperPrefix` directive allows to specify a tag prefix string to enable Tag Helper support and to make Tag Helper usage explicit.
|
||||
|
||||
```cshtml linenums="1"
|
||||
```cshtml
|
||||
@tagHelpersPrefix th:
|
||||
```
|
||||
|
||||
|
@ -74,7 +74,7 @@ The `@tagHelperPrefix` directive allows to specify a tag prefix string to enable
|
|||
|
||||
[Understanding Html Helpers](https://stephenwalther.com/archive/2009/03/03/chapter-6-understanding-html-helpers)
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
@model <App>.Models.Entity
|
||||
|
||||
// Display the name of the property
|
||||
|
@ -112,7 +112,7 @@ The `@tagHelperPrefix` directive allows to specify a tag prefix string to enable
|
|||
|
||||
In `ViewModel.cs`:
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
class ViewModel
|
||||
{
|
||||
public int EntityId { get; set; } // value selected in form ends up here
|
||||
|
@ -126,7 +126,7 @@ class ViewModel
|
|||
|
||||
In `View.cs`
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
@model ViewModel
|
||||
|
||||
<form asp-controller="Controller" asp-action="PostAction">
|
||||
|
@ -140,7 +140,7 @@ In `View.cs`
|
|||
|
||||
In `Controller.cs`:
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
public IActionResult GetAction()
|
||||
{
|
||||
var vm = new ViewModel();
|
||||
|
|
|
@ -8,7 +8,7 @@ The SignalR Hubs API enables to call methods on connected clients from the serve
|
|||
|
||||
In `Startup.cs`:
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
builder.Services.AddSignalR();
|
||||
|
||||
var app = builder.Build();
|
||||
|
@ -21,7 +21,7 @@ app.UseEndpoints(endpoints =>
|
|||
|
||||
### Creating Hubs
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
public class CustomHub : Hub
|
||||
{
|
||||
public task HubMethod(Type args)
|
||||
|
@ -46,7 +46,7 @@ A drawback of using `SendAsync` is that it relies on a magic string to specify t
|
|||
|
||||
An alternative to using SendAsync is to strongly type the Hub with `Hub<T>`.
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
public interface IHubClient
|
||||
{
|
||||
// matches method to be called on the client
|
||||
|
@ -54,7 +54,7 @@ public interface IHubClient
|
|||
}
|
||||
```
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
public class CustomHub : Hub<IHubClient>
|
||||
{
|
||||
public Task HubMethod(Type args)
|
||||
|
@ -72,7 +72,7 @@ Using a strongly typed `Hub<T>` disables the ability to use `SendAsync`. Any met
|
|||
|
||||
The SignalR Hubs API provides the OnConnectedAsync and OnDisconnectedAsync virtual methods to manage and track connections. Override the OnConnectedAsync virtual method to perform actions when a client connects to the Hub, such as adding it to a group.
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
public override async Task OnConnectedAsync()
|
||||
{
|
||||
await Groups.AddToGroupAsync(Context.ConnectionId, "GroupName");
|
||||
|
@ -98,7 +98,7 @@ If the Hub throws an exception, connections aren't closed. By default, SignalR r
|
|||
|
||||
If you have an exceptional condition you *do* want to propagate to the client, use the `HubException` class. If you throw a `HubException` from your hub method, SignalR will send the entire message to the client, unmodified.
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
public Task ThrowException()
|
||||
{
|
||||
throw new HubException("This error will be sent to the client!");
|
||||
|
@ -109,7 +109,7 @@ public Task ThrowException()
|
|||
|
||||
### Installing the client package
|
||||
|
||||
```sh linenums="1"
|
||||
```sh
|
||||
npm init -y
|
||||
npm install @microsoft/signalr
|
||||
```
|
||||
|
@ -118,7 +118,7 @@ npm installs the package contents in the `node_modules\@microsoft\signalr\dist\b
|
|||
|
||||
Reference the SignalR JavaScript client in the `<script>` element. For example:
|
||||
|
||||
```html linenums="1"
|
||||
```html
|
||||
<script src="~/lib/signalr/signalr.js"></script>
|
||||
```
|
||||
|
||||
|
@ -126,7 +126,7 @@ Reference the SignalR JavaScript client in the `<script>` element. For example:
|
|||
|
||||
[Reconnect Clients Docs](https://docs.microsoft.com/en-us/aspnet/core/signalr/javascript-client#reconnect-clients)
|
||||
|
||||
```js linenums="1"
|
||||
```js
|
||||
const connection = new signalR.HubConnectionBuilder()
|
||||
.withUrl("/hub/endpoint")
|
||||
.configureLogging(signalR.LogLevel.Information)
|
||||
|
@ -158,7 +158,7 @@ JavaScript clients call public methods on hubs via the `invoke` method of the `H
|
|||
- The name of the hub method.
|
||||
- Any arguments defined in the hub method.
|
||||
|
||||
```js linenums="1"
|
||||
```js
|
||||
try {
|
||||
await connection.invoke("HubMethod", args);
|
||||
} catch (err) {
|
||||
|
@ -177,6 +177,6 @@ To receive messages from the hub, define a method using the `on` method of the `
|
|||
- The name of the JavaScript client method.
|
||||
- Arguments the hub passes to the method.
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
connection.on("ClientMethod", (args) => { /* ... */});
|
||||
```
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
The fist loaded page is `Default.aspx` and its underlying code.
|
||||
|
||||
```html linenums="1"
|
||||
```html
|
||||
<!-- directive -->
|
||||
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="Project.Default" %>
|
||||
|
||||
|
@ -26,7 +26,7 @@ The fist loaded page is `Default.aspx` and its underlying code.
|
|||
|
||||
### Page Directive
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
<%@ Page Language="C#" // define language used (can be C# or VB)
|
||||
AutoEventWireup="true" // automatically create and setup event handlers
|
||||
CodeBehind="Default.aspx.cs" // define the underlying code file
|
||||
|
@ -35,7 +35,7 @@ The fist loaded page is `Default.aspx` and its underlying code.
|
|||
|
||||
### Web Controls
|
||||
|
||||
```xml linenums="1"
|
||||
```xml
|
||||
<asp:Control ID="" runat="server" ...></asp:Control>
|
||||
|
||||
<!-- Label: empty text will diplay ID, use empty space as text for empty label -->
|
||||
|
@ -59,7 +59,7 @@ The fist loaded page is `Default.aspx` and its underlying code.
|
|||
|
||||
## `Page.aspx.cs`
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
public partial class Default : System.Web.UI.Page
|
||||
{
|
||||
protected void Page_Load(object sender, EventArgs e)
|
||||
|
|
|
@ -14,7 +14,7 @@ In performance-sensitive code, asynchronous APIs are useful, because instead of
|
|||
|
||||
The `async` and `await` keywords in C# are the heart of async programming.
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
public async Task<TResult> MethodAsync
|
||||
{
|
||||
Task<TResult> resultTask = obj.OtherMethodAsync();
|
||||
|
@ -90,7 +90,7 @@ Because `Task` and `Task<TResult>` are **reference types**, memory allocation in
|
|||
|
||||
### Async Composition
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
public async Task DoOperationsConcurrentlyAsync()
|
||||
{
|
||||
Task[] tasks = new Task[3];
|
||||
|
@ -132,7 +132,7 @@ If work starting from a UI thread is performed, but there is no particular need
|
|||
If the asynchronous operation is a `Task`, `Task<T>`, `ValueTask` or `ValueTask<T>`, it's possible to discard the *synchronization context* by calling the `ConfigureAwait(false)`.
|
||||
This returns a different representation of the asynchronous operation, and if this iss awaited that instead of the original task, it will ignore the current `SynchronizationContext` if there is one.
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
private async Task DownloadFileAsync(string fileName)
|
||||
{
|
||||
await OperationAsync(fileName).ConfigureAwait(false); // discarding original context
|
||||
|
@ -156,7 +156,7 @@ This is true even of exceptions thrown before the first `await`.
|
|||
If the calling method immediately calls `await` on the return task, this won’t matter much—it will see the exception in any case.
|
||||
But some code may choose not to wait immediately, in which case it won’t see the argument exception until later.
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
async Task<string> MethodWithValidationAsync(string argument)
|
||||
{
|
||||
if(sting.IsNullOrEmpty(argument))
|
||||
|
@ -173,7 +173,7 @@ async Task<string> MethodWithValidationAsync(string argument)
|
|||
In cases where you want to throw this kind of exception straightaway, the usual technique is to write a normal method that validates the arguments before calling an async method that does the
|
||||
work, and to make that second method either private or local.
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
// not marked with async, exception propagate directly to caller
|
||||
public static Task<string> MethodWithValidationAsync(string argument)
|
||||
{
|
||||
|
|
|
@ -6,7 +6,7 @@ An array is an object that contains multiple elements of a particular type. The
|
|||
|
||||
An array type is always a reference type, regardless of the element type. Nonetheless, the choice between reference type and value type elements makes a significant difference in an array's behavior.
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
type[] array = new type[dimension];
|
||||
type array[] = new type[dimension]; //invalid
|
||||
|
||||
|
@ -24,7 +24,7 @@ array.OfType<Type>(); // filter array based on type, returns IEnumerable<Type>
|
|||
|
||||
### [Array Methods](https://docs.microsoft.com/en-us/dotnet/api/system.array?view=netcore-3.1#methods)
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
// overloaded search methods
|
||||
Array.IndexOf(array, item); // return index of searched item in passed array
|
||||
Array.LastIndexOf(array, item); // return index of searched item staring from the end of the array
|
||||
|
@ -54,7 +54,7 @@ C# supports two multidimensional array forms: [jagged][jagg_arrays] arrays and [
|
|||
[jagg_arrays]: https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/arrays/jagged-arrays
|
||||
[rect_arrays]: https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/arrays/multidimensional-arrays
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
//specify first dimension
|
||||
type[][] jagged = new type[][]
|
||||
{
|
||||
|
@ -87,7 +87,7 @@ matrix.GetLength(int dimension); // get the size of a particular direction
|
|||
|
||||
`List<T>` stores sequences of elements. It can grow or shrink, allowing to add or remove elements.
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
using System.Collections.Generics;
|
||||
|
||||
List<T> list = new List<T>();
|
||||
|
@ -140,7 +140,7 @@ It's possible to use a `yield break` statement or exception to end the iteration
|
|||
|
||||
**Note**: Since an iterator returns an `IEnumerable<T>` is can be used to implement a `GetEnumerator()`.
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
// simple iterator
|
||||
public static System.Collections.IEnumerable<int> IterateRange(int start = 0, int end)
|
||||
{
|
||||
|
@ -156,7 +156,7 @@ public static System.Collections.IEnumerable<int> IterateRange(int start = 0, in
|
|||
|
||||
Exposes the enumerator, which supports a simple iteration over a collection of a specified type.
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
public interface IEnumerable<out T> : IEnumerable
|
||||
{
|
||||
IEnumerator<T> GetEnumerator(); // return an enumerator
|
||||
|
@ -179,7 +179,7 @@ public interface IEnumerator<T>
|
|||
|
||||
### [`ICollection<T>`](https://docs.microsoft.com/en-us/dotnet/api/system.collections.generic.icollection-1)
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
public interface ICollection<T> : IEnumerable<T>
|
||||
{
|
||||
// properties
|
||||
|
@ -197,7 +197,7 @@ public interface ICollection<T> : IEnumerable<T>
|
|||
|
||||
### [`IList<T>`](https://docs.microsoft.com/en-us/dotnet/api/system.collections.generic.ilist-1)
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
public interface IList<T> : ICollection<T>, IEnumerable<T>
|
||||
{
|
||||
// properties
|
||||
|
@ -228,7 +228,7 @@ public interface IList<T> : ICollection<T>, IEnumerable<T>
|
|||
- Enumerating a dictionary will return `KeyValuePair<TKey, TValue>`.
|
||||
- The `Dictionary<TKey, TValue>` collection class relies on hashes to offer fast lookup (`TKey` should have a good `GetHashCode()`).
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
Dictionary<TKey, TValue> dict = new Dictionary<TKey, TValue>(); // init empty dict
|
||||
Dictionary<TKey, TValue> dict = new Dictionary<TKey, TValue>(IEqualityComparer<TKey>); // specify key comparer (TKey must implement Equals() and GetHashCode())
|
||||
|
||||
|
@ -270,7 +270,7 @@ dict.TryGetValue(key, out var); // put the value associated with kay in the var
|
|||
|
||||
Collection of non duplicate items.
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
HashSet<T> set = new HashSet<T>();
|
||||
|
||||
set.Add(T); // adds an item to the set; true if the element is added, false if the element is already present.
|
||||
|
|
|
@ -18,7 +18,7 @@ to native code later.
|
|||
|
||||
### Comments
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
// comment
|
||||
/* multi line comment */
|
||||
/// single line xml comment (docstring)
|
||||
|
@ -44,7 +44,7 @@ to native code later.
|
|||
|
||||
Hierarchic organization of programs an libraries.
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
using System; // import the System Namespace
|
||||
using static System.Console; // statically import a class to use its static methods w/o qualification
|
||||
|
||||
|
@ -65,13 +65,13 @@ namespace Namespace
|
|||
|
||||
To enable .NET 6/C# 10 **implicit namespace imports**:
|
||||
|
||||
```xml linenums="1"
|
||||
```xml
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
```
|
||||
|
||||
### Top Level Statements/Programs (C# 9)
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
// imports
|
||||
|
||||
// code here, no main, no namespace
|
||||
|
@ -79,7 +79,7 @@ To enable .NET 6/C# 10 **implicit namespace imports**:
|
|||
|
||||
### Main Method
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
// code here
|
||||
|
@ -88,7 +88,7 @@ public static void Main(string[] args)
|
|||
|
||||
### Constant Declaration
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
const type CONSTANT_NAME = value;
|
||||
```
|
||||
|
||||
|
@ -100,7 +100,7 @@ If a variable has not been assigned it assumes the `default` value.
|
|||
|
||||
### Input
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
// input is a string, convert before saving in a non String variable
|
||||
Console.ReadLines(); // read util <Return> is pressed
|
||||
Console.Read(); // read until space
|
||||
|
@ -118,7 +118,7 @@ Console.ReadKey(); // read a key from keyboard and display pressed kay immedi
|
|||
|
||||
### Screen Output
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
Console.WriteLine(); // single line output
|
||||
```
|
||||
|
||||
|
@ -126,7 +126,7 @@ Console.WriteLine(); // single line output
|
|||
|
||||
`{index[,alignment][:<formatString><num_decimal_digits>]}`
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
Console.WriteLine("Name is {0}, Marks are {1}", name, marks); // string composite formatting
|
||||
Console.WriteLine($"Name is {name}, Marks are {marks}"); // string interpolation
|
||||
|
||||
|
@ -200,7 +200,7 @@ The static fields and methods of the `MathF` class correspond to those of the `M
|
|||
`BigInteger` represents an integer that will grow as large as is necessary to accommodate values.
|
||||
Unlike the builtin numeric types, it has no theoretical limit on its range.
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
using System;
|
||||
using System.Numerics;
|
||||
|
||||
|
@ -212,7 +212,7 @@ BigInteger bi;
|
|||
Binary literal: `0b<digits>`
|
||||
Hexadecimal literal: `0x<digits>`
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
// three variables that store the number 2 million
|
||||
int decimalNotation = 2_000_000;
|
||||
int binaryNotation = 0b_0001_1110_1000_0100_1000_0000;
|
||||
|
@ -232,19 +232,19 @@ int hexadecimalNotation = 0x_001E_8480;
|
|||
|
||||
The compiler determines the required type based on the assigned value.
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
var variable = value; // Inferred tipe cant change after first assignment
|
||||
```
|
||||
|
||||
### Dynamic Type
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
dynamic variable = value;
|
||||
```
|
||||
|
||||
### Anonymous types (Reference Type)
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
// cannot be used as return types
|
||||
var x = new { Key = value, ...}; // read only properties
|
||||
x.Key; // member access
|
||||
|
@ -260,7 +260,7 @@ A [System.Range][range_type] represents a range that has start and end indexes.
|
|||
[index_type]: https://docs.microsoft.com/en-us/dotnet/api/system.index
|
||||
[range_type]: https://docs.microsoft.com/en-us/dotnet/api/system.range
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
Index i = position;
|
||||
Index i = new Index(position, IsFromEnd: false); // start-relative index
|
||||
|
||||
|
@ -288,7 +288,7 @@ Tuples are designed as a convenient way to package together a few values in case
|
|||
Tuples support comparison, so it's possible to use the `==` and `!=` relational operators.
|
||||
To be considered equal, two tuples must have the same shape and each value in the first tuple must be equal to its counterpart in the second tuple.
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
(Type Var1, Type Var2, ...) variable = (value1, value2, ...);
|
||||
var variable = (Var1: value1, Var2: value2, ...); // if name are not supplied they default to Item1, Item2, ...
|
||||
var variable = (var1, var2); // constructed w/ pre-existing values, tuple attributes named after the variables
|
||||
|
@ -296,14 +296,14 @@ var variable = (var1, var2); // constructed w/ pre-existing values, tuple attri
|
|||
|
||||
Since the names of the attributes of a tuple do not matter (a tuple is an instance of `ValueTuple<Type, Type, ...>`) it's possible to assign any tuple to another tuple with the same structure.
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
(int X, Int Y) a = (1 , 0);
|
||||
(int Width, int Height) b = a;
|
||||
```
|
||||
|
||||
### Tuple Deconstruction
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
(int X, int Y) point = (10, 35);
|
||||
(int a, int b) = point; // extract data based on position into two variables
|
||||
```
|
||||
|
@ -312,7 +312,7 @@ Since the names of the attributes of a tuple do not matter (a tuple is an instan
|
|||
|
||||
I'ts possible to create record types with immutable properties by using standard property syntax or positional parameters:
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
public record Person
|
||||
{
|
||||
public string FirstName { get; init; } = default!;
|
||||
|
@ -333,7 +333,7 @@ public readonly record struct Point(double X, double Y, double Z);
|
|||
|
||||
it's also possible to create record types with mutable properties and fields:
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
// mutable record
|
||||
public record Person
|
||||
{
|
||||
|
@ -361,7 +361,7 @@ While records can be mutable, they're primarily intended for supporting immutabl
|
|||
When working with immutable data, a common pattern is to create new values from existing ones to represent a new state.
|
||||
To help with this style of programming, records allow for a new kind of expression; the with-expression.
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
var newRecord = oldRecord with { Property = value };
|
||||
```
|
||||
|
||||
|
@ -369,7 +369,7 @@ With-expressions use object initializer syntax to state what's different in the
|
|||
A record implicitly defines a protected "copy constructor", a constructor that takes an existing record object and copies it field by field to the new one.
|
||||
The `with` expression causes the copy constructor to get called, and then applies the object initializer on top to change the properties accordingly.
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
protected Record(Record original) { /* copy all the fields */ } // generated
|
||||
```
|
||||
|
||||
|
@ -381,7 +381,7 @@ Records have a hidden virtual method that is entrusted with "cloning" the whole
|
|||
Every derived record type overrides this method to call the copy constructor of that type, and the copy constructor of a derived record chains to the copy constructor of the base record.
|
||||
A with-expression simply calls the hidden "clone" method and applies the object initializer to the result.
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
public record Base{ Type Prop1, Type Prop2 };
|
||||
public record Derived : Base { Type Prop3 };
|
||||
|
||||
|
@ -394,7 +394,7 @@ var newBase = @base with { Prop2 = value }; // new Derived record even if type
|
|||
Records have a virtual protected property called `EqualityContract`.
|
||||
Every derived record overrides it, and in order to compare equal, the two objects musts have the same `EqualityContract`.
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
public record Base{ Type Prop1, Type Prop2 };
|
||||
public record Derived : Base { Type Prop3 };
|
||||
|
||||
|
@ -411,7 +411,7 @@ This creates a lot of extra work for .NET's garbage collector, causing the progr
|
|||
|
||||
In these situations, it's possible to can use a type called `StringBuilder`. This is conceptually similar to a string but it is modifiable.
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
"string contents here" // string literal
|
||||
@"string contents here" // verbatim string, escape characters printed as-is (raw string literal)
|
||||
$"{variable} contents here" // string interpolation
|
||||
|
@ -422,7 +422,7 @@ String.Length // returns the length of the string
|
|||
|
||||
### String Methods (Not In-Place)
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
string_.IndexOf(<character/string>, startIndex, endIndex); // index of first occurrence of character/string, -1 otherwise
|
||||
string_.LastIndexOf(<character/string>, startIndex, endIndex); // index last occurrence of character/string, -1 otherwise
|
||||
string_.IndexOfAny(char_array, startIndex, endIndex); // index of any of the characters in the supplied array
|
||||
|
@ -457,7 +457,7 @@ A raw string literal starts with at least three double-quote (`"""`) characters.
|
|||
Typically, a raw string literal uses three double quotes on a single line to start the string, and three double quotes on a separate line to end the string.
|
||||
The newlines following the opening quote and preceding the closing quote aren't included in the final content:
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
|
||||
string longMessage = """
|
||||
This is a long message.
|
||||
|
@ -473,7 +473,7 @@ string longMessage = """
|
|||
|
||||
Raw string literals can be combined with _string interpolation_ to include braces in the output text. Multiple `$` characters denote how many consecutive braces start and end the interpolation
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
var location = $$"""
|
||||
You are at {{{Longitude}}, {{Latitude}}}
|
||||
""";
|
||||
|
@ -496,7 +496,7 @@ When a nullable type is boxed, the common language runtime automatically boxes t
|
|||
|
||||
If the `HasValue` property of a nullable type is `false`, the result of a boxing operation is `null`. Consequently, if a boxed nullable type is passed to a method that expects an object argument, that method must be prepared to handle the case where the argument is `null`. When `null` is unboxed into a nullable type, the common language runtime creates a new `Nullable<T>` structure and initializes its `HasValue` property to `false`.
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
Type? nullableValueType = default; // assigns null
|
||||
|
||||
nullableValueType.HasValue // boolean, use for null check
|
||||
|
@ -548,7 +548,7 @@ Valid settings are:
|
|||
|
||||
In `Project.csproj`:
|
||||
|
||||
```xml linenums="1"
|
||||
```xml
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
|
@ -562,7 +562,7 @@ In `Project.csproj`:
|
|||
|
||||
In `Program.cs`:
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
#nullable enable // Sets the nullable annotation context and nullable warning context to enabled.
|
||||
#nullable disable // Sets the nullable annotation context and nullable warning context to disabled.
|
||||
#nullable restore // Restores the nullable annotation context and nullable warning context to the project settings.
|
||||
|
@ -576,7 +576,7 @@ In `Program.cs`:
|
|||
|
||||
### Null Conditional, Null Coalescing, Null Forgiving Operator, Null Checks
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
Type? variable = null; // the variable can also contain the NULL value (nullable type)
|
||||
|
||||
<expr>! // declare explicitly that the expression is not null (null forgiving operator)
|
||||
|
@ -627,7 +627,7 @@ That information helps the compiler perform static analysis and determine when a
|
|||
|
||||
## Type Conversion
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
variable.GetType(); // System type of variable
|
||||
|
||||
(type) variable // explicit conversion
|
||||
|
@ -680,7 +680,7 @@ The _.NET SDK_ defines certain symbols by default. It supports two configuration
|
|||
It defines a `DEBUG` compilation symbol in the Debug configuration, whereas Release will define `RELEASE` instead.
|
||||
It defines a symbol called `TRACE` in both configurations.
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
#if DEBUG
|
||||
// instructions
|
||||
#endif
|
||||
|
@ -690,7 +690,7 @@ C# provides a more subtle mechanism to support this sort of thing, called a _con
|
|||
The compiler recognizes an attribute defined by the .NET class libraries, called `ConditionalAttribute`, for which it provides special compile time behavior.
|
||||
Method annotated with this attribute will not be present in a non-Debug release.
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
[System.Diagnostics.Conditional("DEBUG")]
|
||||
Type Method() { ... }
|
||||
```
|
||||
|
@ -699,7 +699,7 @@ Type Method() { ... }
|
|||
|
||||
C# allows choose to generate _compiler errors_ or warnings with the `#error` and `#warning` directives. These are typically used inside conditional regions.
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
#if NETSTANDARD
|
||||
#error .NET Standard is not a supported target for this source file
|
||||
#endif
|
||||
|
@ -710,7 +710,7 @@ C# allows choose to generate _compiler errors_ or warnings with the `#error` and
|
|||
The `#pragma` directive provides two features: it can be used to disable selected compiler warnings, and it can also be used to override the checksum values the compiler puts into the `.pdb` file it generates containing debug information.
|
||||
Both of these are designed primarily for code generation scenarios, although they can occasionally be useful to disable warnings in ordinary code.
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
#pragma warning disable CS<number>
|
||||
```
|
||||
|
||||
|
@ -809,7 +809,7 @@ Both of these are designed primarily for code generation scenarios, although the
|
|||
|
||||
### `If`-`Else If`-`Else`
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
Object o;
|
||||
|
||||
if (condition)
|
||||
|
@ -832,7 +832,7 @@ else
|
|||
|
||||
A pattern describes one or more criteria that a value can be tested against. It's usable in switch statements, switch expressions and if statements.
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
// type pattern
|
||||
<expr> is Type t // type pattern
|
||||
|
||||
|
@ -885,7 +885,7 @@ The `when` keyword can be used to specify a filter condition that causes its ass
|
|||
|
||||
[Switch Expressions](https://dotnetcoretutorials.com/2019/06/25/switch-expressions-in-c-8/)
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
switch (expr)
|
||||
{
|
||||
// multiple labels for same block
|
||||
|
@ -924,7 +924,7 @@ variable switch
|
|||
|
||||
### `While` Loop
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
while (condition)
|
||||
{
|
||||
// code here
|
||||
|
@ -935,7 +935,7 @@ while (condition)
|
|||
|
||||
Executes at least one time.
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
do
|
||||
{
|
||||
// code here
|
||||
|
@ -945,7 +945,7 @@ while (condition);
|
|||
|
||||
### `For` Loop
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
for (initializer; condition; iterator)
|
||||
{
|
||||
// code here
|
||||
|
@ -962,7 +962,7 @@ Technically, the `foreach` statement will work on any type that follows these ru
|
|||
|
||||
There are interfaces named `IEnumerable` and `IEnumerable<T>` that formally define these rules but technically the compiler does not require the type to implement these interfaces.
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
foreach (type item in iterabile)
|
||||
{
|
||||
// code here
|
||||
|
@ -974,7 +974,7 @@ foreach (type item in iterabile)
|
|||
|
||||
Example:
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
// make integers enumerable
|
||||
public static IEnumerator<int> GetEnumerator(this int source)
|
||||
{
|
||||
|
@ -992,14 +992,14 @@ public static IEnumerator<int> GetEnumerator(this int source)
|
|||
|
||||
### Yield Statement
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
yield return <expression>; // returns the results one at a time.
|
||||
yield break; // concludes the iteration
|
||||
```
|
||||
|
||||
### Context Statement & Using Declarations
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
using (Type obj = new Type()) // obj disposed at the end of the using block
|
||||
{
|
||||
// code here
|
||||
|
@ -1023,7 +1023,7 @@ It is done by editing the `.csproj` file, adding `<CheckForOverflowUnderflow>tru
|
|||
|
||||
> **Note**: checking can make individual integer operations several times slower.
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
checked
|
||||
{
|
||||
// code here
|
||||
|
@ -1045,7 +1045,7 @@ unchecked(<expr>);
|
|||
|
||||
[Exception Object](https://docs.microsoft.com/en-us/dotnet/api/system.exception)
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
try
|
||||
{
|
||||
// "dangerous" code
|
||||
|
@ -1071,7 +1071,7 @@ finally
|
|||
|
||||
### Throwing Exceptions
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
throw new ExceptionClass();
|
||||
throw new ExceptionClass("message");
|
||||
|
||||
|
@ -1092,7 +1092,7 @@ Environment.FailFast(causeOfFailure);
|
|||
|
||||
### Custom Exceptions
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
public class CustomException : Exception // must derive from Exception (either directly or indirectly)
|
||||
{
|
||||
public CustomException()
|
||||
|
@ -1118,7 +1118,7 @@ public class CustomException : Exception // must derive from Exception (either
|
|||
An enumeration type (or enum type) is a value type defined by a set of **named constants** of the underlying _integral numeric_ type (`int`, `long`, `byte`, ...).
|
||||
Consecutive names increase the value by one.
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
[Flags] // indicate that the flag can be combined (best if values are binary) as a bit mask
|
||||
enum EnumType : IntegralNumericType // named values MUST match IntegerNumericType allowed values
|
||||
{
|
||||
|
@ -1153,7 +1153,7 @@ The method signature is the number & type of the input parameters defined for th
|
|||
C# makes the fairly common distinction between _parameters_ and _arguments_: a method defines a list of the inputs it expects (the parameters) and the code inside the method refers to these parameters by name.
|
||||
The values seen by the code could be different each time the method is invoked, and the term argument refers to the specific value supplied for a parameter in a particular invocation.
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
type MethodName (type parameter, ...)
|
||||
{
|
||||
// code here
|
||||
|
@ -1168,13 +1168,13 @@ void MethodName (type parameter, ...) {
|
|||
|
||||
### Expression Body Definition
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
type MethodName() => <expression>; // expression result type MUST match method type
|
||||
```
|
||||
|
||||
### Arbitrary Number Of Parameter In Methods
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
// params keyword must be last parameter and must be an array
|
||||
type MethodName (type parameter, params type[] args)
|
||||
{
|
||||
|
@ -1184,7 +1184,7 @@ type MethodName (type parameter, params type[] args)
|
|||
|
||||
### [Named Arguments](https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/named-and-optional-arguments#named-arguments)
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
type MethodName (type param1, type param2, ...) { }
|
||||
|
||||
MethodName(param1: value, param2: value);
|
||||
|
@ -1208,7 +1208,7 @@ A default value must be one of the following types of expressions:
|
|||
- an expression of the form new ValType(), where ValType is a value type, such as an enum or a struct;
|
||||
- an expression of the form default(ValType), where ValType is a value type.
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
type MethodName (type required, type firstOptional = default_value, type secondOptional = default_value, ...) { }
|
||||
MethodName(value1); // use defaults for optional arguments
|
||||
MethodName(required: value, secondOptional: value); // use default for first optional but pass second optional
|
||||
|
@ -1241,7 +1241,7 @@ Use cases:
|
|||
While the method can use members of the passed reference type, it can't normally replace it with a different object.
|
||||
But if a reference type argument is marked with ref, the method has access to the variable, so it could replace it with a reference to a completely different object.
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
// method declaration
|
||||
type MethodName (type param1, ref type param2, out type param3, in type param4, ...)
|
||||
{
|
||||
|
@ -1261,7 +1261,7 @@ OutMethod(arg1, out var arg2); // create out variable on the fly
|
|||
**Must** be C# 7+.
|
||||
The retuned tuple MUST match the tuple-type in the instantiation
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
(type returnedVar1, type returnedVar2, ...) MethodName (type parameter, ...)
|
||||
{
|
||||
// code here
|
||||
|
@ -1271,7 +1271,7 @@ The retuned tuple MUST match the tuple-type in the instantiation
|
|||
|
||||
### Returning Multiple Values W/ Structs (Return Struct Variable)
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
StructName MethodName (args)
|
||||
{
|
||||
// code here
|
||||
|
@ -1285,7 +1285,7 @@ StructName MethodName (args)
|
|||
|
||||
### Local Functions
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
type OuterMethod(...)
|
||||
{
|
||||
var foo = InnerMethod();
|
||||
|
@ -1302,7 +1302,7 @@ It's just an illusion maintained by the C# compiler, one that it keeps up even i
|
|||
|
||||
> **Note**: Extension Method can be declared only inside static classes. Extension methods are available only if their namespace is imported with the `using` keyword.
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
public static class ExtensionMethods
|
||||
{
|
||||
type ExtensionMethod(this type param)
|
||||
|
@ -1328,7 +1328,7 @@ It's possible to use a `yield break` statement or exception to end the iteration
|
|||
|
||||
> **Note**: Since an iterator returns an `IEnumerable<T>` is can be used to implement a `GetEnumerator()`.
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
// simple iterator
|
||||
public static System.Collections.IEnumerable<int> IterateRange(int start = 0, int end)
|
||||
{
|
||||
|
@ -1361,7 +1361,7 @@ Modifiable value types tend to be problematic, because it's all too easy to end
|
|||
So it's usually a good idea for value types to be immutable. This doesn't mean that variables of these types cannot be modified;
|
||||
it just means that to modify the variable, its contents must be replaced entirely with a different value.
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
public struct Point
|
||||
{
|
||||
public Point(double x, double y)
|
||||
|
@ -1390,7 +1390,7 @@ If you attempt to access the variable outside of the code block, you'll get a co
|
|||
|
||||
[Access Modifiers](https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/access-modifiers)
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
// ACCESS MODIFIERS
|
||||
public // visible from everywhere
|
||||
private // not visible outside of the class (default for members)
|
||||
|
@ -1424,7 +1424,7 @@ If any part declares a base type, then the whole type inherits that class.
|
|||
|
||||
### Methods
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
class Class
|
||||
{
|
||||
static Type Method(Type Argument, ...) {} // static method, can operate ONLY on STATIC VARIABLES
|
||||
|
@ -1473,7 +1473,7 @@ class Class(Type Parameter, ...) // primary constructor (like records)
|
|||
A _field_ is a variable of any type that is declared directly in a class or struct. Fields are members of their containing type.
|
||||
A _property_ is a member that provides a flexible mechanism to read, write, or compute the value of a private field.
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
class Class
|
||||
{
|
||||
|
||||
|
@ -1531,7 +1531,7 @@ Because `init` accessors can only be called during initialization, they are allo
|
|||
**Object initializers** allow to assign values to any accessible fields or properties of an object at creation time without having to invoke a constructor followed by lines of assignment statements.
|
||||
The object initializer syntax enables to specify arguments for a constructor or omit the arguments (and parentheses syntax).
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
public class Class
|
||||
{
|
||||
// Auto-implemented properties.
|
||||
|
@ -1563,7 +1563,7 @@ Class obj = new Class(arg1) { Prop2 = arg2 }; // w/ constructor
|
|||
var copy = original with { Prop = newValue }; // other props are copies of the original
|
||||
```
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
public class Matrix
|
||||
{
|
||||
private double[,] matrix = new double[3, 3];
|
||||
|
@ -1631,7 +1631,7 @@ Dictionary<int, string> digits = [
|
|||
The `static` keyword declares that a member is not associated with any particular instance of the class.
|
||||
Static classes **can't** instantiate objects and all their methods **must** be static.
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
static class Class
|
||||
{
|
||||
// static constructor, not called explicitly, has no arguments
|
||||
|
@ -1672,7 +1672,7 @@ static class Class
|
|||
An **indexer** is a property that takes one or more arguments, and is accessed with the same syntax as is used for arrays.
|
||||
This is useful when writing a class that contains a collection of objects.
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
public class Class<T>
|
||||
{
|
||||
public T this[int i]
|
||||
|
@ -1718,7 +1718,7 @@ Members marked as `abstract` must be implemented by non-abstract classes that de
|
|||
- It is an error to use the `abstract` modifier on a `static` property.
|
||||
- An `abstract` inherited property can be overridden in a derived class by including a property declaration that uses the `override` modifier.
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
public abstract class Abstract : Interface
|
||||
{
|
||||
public abstract Type Property { get; set; }
|
||||
|
@ -1743,7 +1743,7 @@ public class Derived : Abstract
|
|||
|
||||
### Cloning
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
Class obj = new Class()
|
||||
|
||||
Object.MemberwiseClone(); // Returns shallow copy of the object
|
||||
|
@ -1756,7 +1756,7 @@ Deconstruction is not limited to tuples. By providing a `Deconstruct(...)` metho
|
|||
|
||||
> **Note**: Types with a deconstructor can also use _positional pattern matching_.
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
public readonly struct Size
|
||||
{
|
||||
public Size(double w, double h)
|
||||
|
@ -1809,7 +1809,7 @@ Use the operator keyword to declare an operator. An operator declaration must sa
|
|||
|
||||
[Overloadable operators](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/operators/operator-overloading#overloadable-operators)
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
using System;
|
||||
|
||||
public readonly struct Fraction
|
||||
|
@ -1899,7 +1899,7 @@ An interface is effectively a list of the members that a type will need to provi
|
|||
|
||||
C# 8.0 adds the ability to define default implementations for some or all methods, and also to define nested types and static fields.
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
// can only be public or internal if not nested, any accessibility otherwise
|
||||
public interface IContract
|
||||
{
|
||||
|
@ -1956,7 +1956,7 @@ which is effectively an object that holds a copy of a struct in a way that can b
|
|||
[Generics Docs](https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/generics/)
|
||||
[Generic Methods Docs](https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/generics/generic-methods)
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
// type parameter T in angle brackets
|
||||
// WARNING: T is not instantiable, new t(), new t[] are INVALID
|
||||
public class GenericClass<T> {
|
||||
|
@ -1983,7 +1983,7 @@ obj.GenericMethodName(Type param); // type deduced by input, input type and gen
|
|||
|
||||
### Multiple Generics
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
public class GenericClass<T1, T2, ...> { } // number of generic types is not limited
|
||||
```
|
||||
|
||||
|
@ -2000,7 +2000,7 @@ C# supports only six kinds of constraints on a type argument:
|
|||
- `unmanaged`
|
||||
- `new()`
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
// type constraints
|
||||
public class GenericClass<T> where T : Interface { }
|
||||
public class GenericClass<T> where T: GenericClass { }
|
||||
|
@ -2049,7 +2049,7 @@ both public and private—an instance of the derived class can do anything an in
|
|||
> **Note**: When deriving from a class, it's not possible to make the derived class more visible than its base. This restriction does not apply to interfaces.
|
||||
A `public` class is free to implement `internal` or `private` interfaces. However, it does apply to an interface's bases: a `public` interface cannot derive from an `internal` interface.
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
class BaseClass
|
||||
{
|
||||
public virtual Property { get; set; }
|
||||
|
@ -2074,7 +2074,7 @@ class ChildClass : BaseClass, Interface, Interface<Type>
|
|||
|
||||
Downcasting is the conversion from a base class type to one of it's derived types.
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
Base b;
|
||||
var d = (Derived) b; // explicit casting (if conversion fails throws InvalidCastException)
|
||||
var d = b as Derived; // as operator (if conversion fails AS will return NULL)
|
||||
|
@ -2095,7 +2095,7 @@ Initialization order:
|
|||
3. Base class constructor
|
||||
4. Derived class constructor
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
public class Base
|
||||
{
|
||||
public Base(Type param) {}
|
||||
|
@ -2113,7 +2113,7 @@ public class Derived
|
|||
If you derive from a generic class, you must supply the type arguments it requires.
|
||||
You must provide concrete types unless your derived type is generic, in which case it can use its own type parameters as arguments.
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
public class GenericBase1<T>
|
||||
{
|
||||
public T Item { get; set; }
|
||||
|
@ -2132,7 +2132,7 @@ public class MixedDerived<T> : GenericBase2<T, Type> // derived is generic but
|
|||
|
||||
It's allowed to use derived type as a type argument to the base class. And it's also possible to specify a constraint on a type argument requiring it to derive from the derived type.
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
public class Derived : base<Derived> {}
|
||||
public class Derived<T> where T : Derived<T>
|
||||
```
|
||||
|
@ -2152,7 +2152,7 @@ Generic type parameters support covariance and contravariance to provide greater
|
|||
|
||||
> **Note**: annotate generic type parameters with `out` and `in` annotations to specify whether they should behave covariantly or contravariantly.
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
public class Base {};
|
||||
public class Derived : Base {}
|
||||
|
||||
|
@ -2194,7 +2194,7 @@ This ability to refer to a method as a parameter makes delegates ideal for defin
|
|||
Any method from any accessible class or struct that matches the delegate type can be assigned to the delegate. The method can be either static or an instance method.
|
||||
This makes it possible to programmatically change method calls, and also plug new code into existing classes.
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
// delegate definition
|
||||
public delegate Type Delegate(Type param, ...); // can take any method with specified type params and return type
|
||||
public delegate Type Delegate<T>(T param); // generic delegate
|
||||
|
@ -2208,7 +2208,7 @@ Delegate<Type> delegate = Method; // implicit creation
|
|||
|
||||
**Multicast Delegates** are delegates that can have more than one element in their invocation list.
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
Delegate<Type> multicastDelegate = Method1 + Method2 + ...; // multicast delegate creation
|
||||
multicastDelegate += Method; // add method to delegate
|
||||
multicastDelegate -= Method; // remove method from delegate
|
||||
|
@ -2222,7 +2222,7 @@ Subtraction of a multicast delegate succeeds only if the delegate from which sub
|
|||
Invoking a delegate with a single target method works as though the code had called the target method in the conventional way.
|
||||
Invoking a multicast delegate is just like calling each of its target methods in turn.
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
Delegate<Type> delegate = Method;
|
||||
|
||||
delegate(args); // use delegate as standard method
|
||||
|
@ -2235,7 +2235,7 @@ multicastDelegate.GetInvocationList(); // list of methods called by the delegat
|
|||
|
||||
> **Note**: Each delegate has an overload taking from zero to 16 arguments;
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
public delegate void Action<in T1, ...>(T1 arg1, ...);
|
||||
public delegate TResult Func<in T1, ..., out TResult>(T1 arg1, ...);
|
||||
public delegate bool Predicate<in T1, ...>(T1 arg1, ...);
|
||||
|
@ -2250,7 +2250,7 @@ However, the type system supports certain implicit reference conversions for gen
|
|||
|
||||
Delegates without explicit separated method.
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
// lambda variations
|
||||
Delegate<Type> lambda = () => <expr>;
|
||||
Delegate<Type> lambda = input => <expr>;
|
||||
|
@ -2288,7 +2288,7 @@ Structs and classes can declare events. This kind of member enables a type to pr
|
|||
The class who raises events is called _Publisher_, and the class who receives the notification is called _Subscriber_. There can be multiple subscribers of a single event.
|
||||
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 linenums="1"
|
||||
```cs
|
||||
public delegate void EventDelegate(object sender, CustomEventArgs args); // called on event trigger
|
||||
|
||||
public class Publisher
|
||||
|
@ -2305,7 +2305,7 @@ public class Publisher
|
|||
|
||||
### Registering Event Handlers
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
public class Subscriber
|
||||
{
|
||||
Publisher publisher = new Publisher();
|
||||
|
@ -2326,7 +2326,7 @@ public class Subscriber
|
|||
Typically, any event should include two parameters: the _source_ of the event and event _data_.
|
||||
The `EventHandler` delegate is used for all events that do not include event data, the `EventHandler<TEventArgs>` delegate is used for events that include data to be sent to handlers.
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
public class Publisher
|
||||
{
|
||||
public event EventHandler Event;
|
||||
|
@ -2352,7 +2352,7 @@ public class Subscriber
|
|||
|
||||
### Custom Event Args
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
public class CustomEventArgs : EventArgs { }
|
||||
|
||||
public class Publisher
|
||||
|
@ -2533,7 +2533,7 @@ To be used as an attribute, a type must derive from the `System.Attribute` class
|
|||
|
||||
It's possible to pass arguments to the attribute _constructor_ in the annotation.
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
[AttName] // simple attribute
|
||||
|
||||
[AttName(value)] // valorize private fields (through the constructor)
|
||||
|
@ -2544,7 +2544,7 @@ It's possible to pass arguments to the attribute _constructor_ in the annotation
|
|||
|
||||
### Multiple Attributes
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
[Attribute1]
|
||||
[Attribute2]
|
||||
|
||||
|
@ -2553,7 +2553,7 @@ It's possible to pass arguments to the attribute _constructor_ in the annotation
|
|||
|
||||
### Defining Custom Attribute Types
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
// specify what the attribute can be applied to (enforced by c# compiler)
|
||||
[AttributeUsage(AttributeTargets.<TargetType>)]
|
||||
public class CustomAttribute : Attribute
|
||||
|
@ -2571,7 +2571,7 @@ public class CustomAttribute : Attribute
|
|||
It's possible to discover which attributes have been applied through the reflection API.
|
||||
The various targets of attribute have a reflection type representing them (`MethodInfo`, `PropertyInfo`, ...) which all implement the interface `ICustomAttributeProvider`.
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
public interface ICustomAttributeProvider
|
||||
{
|
||||
object[] GetCustomAttributes(bool inherit);
|
||||
|
@ -2590,7 +2590,7 @@ A console application uses streams to represent its input and output.
|
|||
The `Stream` class is defined in the `System.IO` namespace.
|
||||
It is an abstract base class, with concrete derived types such as `FileStream` or `GZipStream` representing particular kinds of streams.
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
// The most important members of Stream
|
||||
public abstract int Read(byte[] buffer, int offset, int count);
|
||||
public abstract void Write(byte[] buffer, int offset, int count);
|
||||
|
@ -2619,7 +2619,7 @@ This is not guaranteed to work because it's not always possible to support it. S
|
|||
Stream also defines a Seek method, this allows to specify the position required relative to the stream's current position.
|
||||
Passing `SeekOrigin.Current` as second argument will set the position by adding the first argument to the current position.
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
public abstract long Seek(long offset, SeekOrigin origin); // offset can be negative
|
||||
```
|
||||
|
||||
|
@ -2650,7 +2650,7 @@ It's possible to constructing them by passing a `Stream` as a constructor argume
|
|||
|
||||
[Encoding](https://docs.microsoft.com/en-us/dotnet/api/system.text.encoding)
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
// Will detect encoding from stream contents
|
||||
StreamReader file = new StreamReader(string path);
|
||||
StreamReader file = new StreamReader(string path, System.Text.Encoding encoding); // encoding is System.Text.Encoding
|
||||
|
@ -2697,7 +2697,7 @@ The `FileStream` class derives from `Stream` and represents a file from the file
|
|||
It' common to use the constructors in which the `FileStream` uses OS APIs to create the file handle. It's possible to provide varying levels of detail on how this si to be done.
|
||||
At a minimum the file's path and a value from the `FileMode` enumeration must be provided.
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
// overloaded FileStream Constructors
|
||||
public FileStream(string path, FileMode mode);
|
||||
public FileStream(string path, FileMode mode, FileAccess access);
|
||||
|
@ -2741,7 +2741,7 @@ public FileStream(string path, FileMode mode, FileAccess access, FileShare share
|
|||
|
||||
> **Note**: The `WriteThrough` flag will ensure that when the stream is disposed or flushed, all the data written will have been delivered to the drive, but the drive will not necessarily have written that data persistently (drives can defer writing for performance), so data loss id still possible if the power fails.
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
// object to read or write to a file (file can be binary)
|
||||
{
|
||||
using(FileStream fstream = new FileStream(path, FileMode.OpenOrCreate, FileAccess.ReadWrite))
|
||||
|
@ -2755,7 +2755,7 @@ public FileStream(string path, FileMode mode, FileAccess access, FileShare share
|
|||
|
||||
The static `File` class provides methods for performing various operations on files.
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
File.Create(string path); // Return Read/Write FileStream to file
|
||||
File.Open(string path, System.IO.FileMode mode); // Open a FileStream on the specified path with read/write access with no sharing.
|
||||
File.Open(string path, System.IO.FileMode mode, System.IO.FileAccess access); // Opens a FileStream on the specified path, with the specified mode and access with no sharing.
|
||||
|
@ -2795,7 +2795,7 @@ File.Replace(string sourceFileName, string destinationFileName, string destinati
|
|||
|
||||
Exposes static methods for creating, moving, and enumerating through directories and subdirectories.
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
Directory.CreateDirectory(string path); // Create directory as specified
|
||||
Directory.Delete(string path); // Delete an empty directory from a specified path (dir must be writable)
|
||||
Directory.Delete(string path, bool recursive); // Delete the specified directory and, if indicated, any subdirectories and files in the directory
|
||||
|
@ -2823,7 +2823,7 @@ Directory.GetFileSystemEntries (string path, string searchPattern, SearchOption
|
|||
|
||||
### [Path](https://docs.microsoft.com/en-us/dotnet/api/system.io.path) Class
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
Combine(string path1, string path2); // Combine two strings into a path
|
||||
Combine(string[] paths); // Combine strings into a path
|
||||
|
||||
|
@ -2870,7 +2870,7 @@ Classes to hold multiple info about a file or directory. If some property change
|
|||
|
||||
Types are required to opt into CLR serialization. .NET defines a `[Serializable]` attribute that must be present before the CLR will serialize the type (class).
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
[Serializable]
|
||||
class Class { }
|
||||
```
|
||||
|
@ -2887,7 +2887,7 @@ Serialization works directly with an object's fields. It uses reflection, which
|
|||
|
||||
Object that represents the difference between two dates
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
TimeSpan Interval = new DateTime() - new DateTime() // difference between dates
|
||||
|
||||
// constructors
|
||||
|
@ -2920,7 +2920,7 @@ length.
|
|||
|
||||
Access to a span contents is done like an and since a `Span<T>` knows its own length, its indexer checks that the index is in range, just as the built-in array type does.
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
Span<int> numbers = stackalloc int[] { 1, 2, 3 };
|
||||
var first = numbers[0];
|
||||
```
|
||||
|
@ -2960,7 +2960,7 @@ This makes these memory types useful when you want something span-like, but in a
|
|||
|
||||
[regex reference](https://docs.microsoft.com/en-us/dotnet/standard/base-types/regular-expression-language-quick-reference)
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
Match match = Regex.Match(string, pattern, regexOptions);
|
||||
|
||||
match.Success; // whether there was a match or not
|
||||
|
@ -2997,7 +2997,7 @@ The `fixed` statement sets a pointer to a managed variable and "pins" that varia
|
|||
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 linenums="1"
|
||||
```cs
|
||||
unsafe Type UnsafeMethod() { /* unsafe context */ }
|
||||
// or
|
||||
unsafe
|
||||
|
@ -3023,7 +3023,7 @@ unsafe
|
|||
|
||||
### Native Memory
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
unsafe
|
||||
|
@ -3040,7 +3040,7 @@ 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 linenums="1"
|
||||
```cs
|
||||
[DllImport("avifil32.dll")]
|
||||
private static extern void AVIFileInit();
|
||||
```
|
||||
|
@ -3051,14 +3051,14 @@ Methods needed to implement a behaviour which do not need an interface to work.
|
|||
|
||||
### Enumerable
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
public bool MoveNext(/* ... */);
|
||||
public T Current { get; }
|
||||
```
|
||||
|
||||
### Awaitable
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
public TaskAwaiter GetAwaiter(/* ... */);
|
||||
```
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@ LINQ to Objects will be used when any `IEnumerable<T>` is specified as the sourc
|
|||
All query expressions are required to begin with a `from` clause, which specifies the source of the query.
|
||||
The final part of the query is a `select` (or `group`) clause. This determines the final output of the query and its system type.
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
// query expression
|
||||
var result = from item in enumerable select item;
|
||||
|
||||
|
@ -35,7 +35,7 @@ var result = from item in enumerable group item by item.property; // returns IE
|
|||
The compiler converts all query expressions into one or more method calls. Once it has done that, the LINQ provider is selected through exactly the same mechanisms that C# uses for any other method call.
|
||||
The compiler does not have any built-in concept of what constitutes a LINQ provider.
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
// expanded query expression
|
||||
var result = Enumerable.Where(item => condition).Select(item => item);
|
||||
```
|
||||
|
@ -44,7 +44,7 @@ The `Where` and `Select` methods are examples of LINQ operators. A LINQ operator
|
|||
|
||||
### Methods on `Enumerable` or `IEnumerable<T>`
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
Enumerable.Range(int start, int end); // IEnumerable<int> of values between start & end
|
||||
|
||||
IEnumerable<TSource>.Select(Func<TSource, TResult> selector); // map
|
||||
|
@ -77,7 +77,7 @@ IEnumerable<TFirst>.Zip(IEnumerable<TSecond> enumerable); // Produces a sequence
|
|||
|
||||
> **Note**: `Enumerable` provides a set of `static` methods for querying objects that implement `IEnumerable<T>`. Most methods are extensions of `IEnumerable<T>`
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
Enumerable.Method(IEnumerable<T> source, args);
|
||||
// if extension method same as
|
||||
IEnumerable<T>.Method(args);
|
||||
|
|
|
@ -19,7 +19,7 @@ Because Rx implements standard LINQ operators, it's possible to write queries ag
|
|||
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 linenums="1"
|
||||
```cs
|
||||
public interface IObservable<out T>
|
||||
{
|
||||
IDisposable Subscribe(IObserver<T> observer);
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
## xUnit
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
using System;
|
||||
using Xunit;
|
||||
|
||||
|
@ -37,7 +37,7 @@ For context cleanup, add the `IDisposable` interface to the test class, and put
|
|||
|
||||
## Mocking with Moq
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
var mockObj = new Mock<MockedType>();
|
||||
|
||||
mockObj.Setup(m => m.Method(It.IsAny<InputType>())).Returns(value);
|
||||
|
|
|
@ -27,7 +27,7 @@ The `ADO.NET` classes are found in `System.Data.dll`, and are integrated with th
|
|||
|
||||
## Connection to DB
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
using System;
|
||||
using System.Data.SqlClient; // ADO.NET Provider, installed through NuGet
|
||||
|
||||
|
@ -55,7 +55,7 @@ namespace <namespace>
|
|||
|
||||
### `SqlConnection`
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
using (SqlConnection connection = new SqlConnection())
|
||||
{
|
||||
connection.ConnectionString = connectionString.ConnectionString;
|
||||
|
@ -70,7 +70,7 @@ using (SqlConnection connection = new SqlConnection(connectionString)) {
|
|||
|
||||
### [SqlCommand](https://docs.microsoft.com/en-us/dotnet/api/system.data.sqlclient.sqlcommand)
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
string sql = "<sql_instruction>";
|
||||
|
||||
using (SqlCommand command = new SqlCommand())
|
||||
|
@ -94,7 +94,7 @@ using (SqlCommand command = new SqlCommand())
|
|||
|
||||
### `SqlDataReader`
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
using (SqlDataReader cursor = command.ExecuteReader()) // object to get data from db
|
||||
{
|
||||
while (cursor.Read()) // get data till possible
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
## Model & Data Annotations
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
@ -35,7 +35,7 @@ NuGet Packages to install:
|
|||
- `Microsoft.EntityFrameworkCore.Design` *or* `Microsoft.EntityFrameworkCore.<db_provider>.Design` needed for tools to work (bundled w\ tools)
|
||||
- `Microsoft.EntityFrameworkCore.<db_provider>`
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace <Project>.Model
|
||||
|
@ -69,14 +69,14 @@ Create & Update DB Schema if necessary.
|
|||
|
||||
In Package Manager Shell:
|
||||
|
||||
```ps1 linenums="1"
|
||||
```ps1
|
||||
PM> Add-Migration <migration_name>
|
||||
PM> update-database [-Verbose] # use the migrations to modify the db, -Verbose to show SQL queries
|
||||
```
|
||||
|
||||
In dotnet cli:
|
||||
|
||||
```ps1 linenums="1"
|
||||
```ps1
|
||||
dotnet tool install --global dotnet-ef # if not already installed
|
||||
|
||||
dotnet ef migrations add <migration_name>
|
||||
|
@ -87,7 +87,7 @@ dotnet ef database update
|
|||
|
||||
### Create
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
context.Add(entity);
|
||||
context.AddRange(entities);
|
||||
|
||||
|
@ -98,7 +98,7 @@ context.SaveChanges();
|
|||
|
||||
[Referenced Object Not Loading Fix](https://stackoverflow.com/a/5385288)
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
context.Entities.ToList();
|
||||
context.Entities.Find(id);
|
||||
|
||||
|
@ -108,7 +108,7 @@ context.Entities.Include(c => c.ForeignObject).Find(id);
|
|||
|
||||
### Update
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
context.Entities.Update(entity);
|
||||
context.UpdateRange(entities);
|
||||
|
||||
|
@ -117,7 +117,7 @@ context.SaveChanges();
|
|||
|
||||
### Delete
|
||||
|
||||
```cs linenums="1"
|
||||
```cs
|
||||
context.Entities.Remove(entity);
|
||||
context.RemoveRange(entities);
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue