乘風破浪,遇見最佳跨平臺跨終端框架.Net Core/.Net生態 - 來自伊朗阿里巴巴旅遊公司的ASP.NET Core知識點和麪試題

前言

https://www.alibabatravels.co

image

無意中看到一套來自伊朗阿里巴巴旅遊公司的ASP.NET Core知識點和麪試題。

注意這個Alibaba Travels Co.和我們中國的阿里巴巴不是一回事。

自我介紹

  • 您最近參與的很酷的項目是什麼?
  • 對於您使用的開發人員工具,您喜歡哪些方面?
  • 在開發者社區中,誰激勵了你?
  • 你有什麼寵物項目嗎?何等?
  • 你昨天/這周學到了什麼?
  • 你對編碼有什麼興奮或興趣?
  • 您最近遇到的技術挑戰是什麼,您是如何解決的?
  • 您能解釋一下在前端安全方面解決的任何常用技術或最近解決的問題嗎?
  • 您個人在最近的項目中採取了哪些措施來提高代碼的可維護性?
  • 談談您的首選開發環境。
  • 您熟悉哪些版本控制系統?
  • 您能描述一下您在創建網頁時的工作流程嗎?
  • 如果您今年可以掌握一項技術,那會是什麼?
  • 你是如何處理與老闆或合作者的分歧的?
  • 您使用哪些資源來了解開發中的最新技術?

知識點

面向對象編程(Object-Oriented Programming)

  • Paradigm
  • Principles
    • Inheritance

    • Encapsulation and Information Hiding

    • Method Hiding and Overriding

    • Abstraction

      • Data Abstraction
      • Procedural (Process,Control) Abstraction
      • Procedural Abstraction by Parameterization
      • Procedural Abstraction by Specification
    • Polymorphism

      • Ad hoc Polymorphism
      • Overloading Polymorphism
      • Coercion Polymorphism
      • Universal Polymorphism
      • Inclusion Polymorphism
      • Parametric polymorphism
      • Invariant Parametric polymorphism
      • Covariant Parametric polymorphism
      • Contravariant Parametric polymorphism
    • Dispatch

      • Static Dispatch
      • Dynamic Dispatch
      • Single dynamic dispatch
      • Multiple dynamic dispatch

.NET

  • Common Language Runtime

    • Intermediate Language (IL)
    • Managed language
    • Managed code
    • Just-In-Time (JIT)
  • Frameworks and Base Class Libraries

    • The Base Class Libraries (BCL)
    • Application framework layers
    • .NET Standard
      image
  • Data Types and Memory Allocation

    • Value Types
    • Reference Types
    • double Versus decimal
    • Stack
    • Heap
  • Local method

  • CLR behind the scene implementations

  • new versus override

  • Initialization order

  • Boxing and unboxing

  • Struct

  • Ref Structs

  • Friend Assemblies

  • Interface implementations

  • Enum Type-Safety Issues

  • Generics

    • Constraints
    • Covariance
    • Contravariance
  • Events

  • Delegate

    • Parameter compatibility
    • Return type compatibility
    • Generic delegate type
  • Lambda Expressions

    • Closures
    • Captured variables
    • Expression tree
    • Lambda Expressions Versus Local Methods
  • try Statements and Exceptions

  • Enumeration and Iterators

  • The Array Class

  • Nullable<T> Struct

  • Nullable Reference Types

  • Extension Methods

  • Anonymous Types

  • Tuple and ValueTuple

  • Patterns

    • Property Patterns
    • Tuple Patterns
    • Positional Patterns
    • var Patterns
    • Constant Patterns
  • Caller Info Attributes

    • CallerMemberName
    • CallerFilePath
    • CallerLineNumber
  • Dynamic Binding

  • Unsafe Code and Pointers

  • Preprocessor Directives

    • Conditional Attributes
  • Comparing Strings

    • Equality comparison
    • Order comparison
      • Ordinal versus culture comparison
  • StringBuilder

  • Text Encodings and Unicode

  • Dates and Times

    • TimeSpan
    • DateTime and DateTimeOffset
    • Time Zones
    • Alternatives
  • BigInteger

  • Complex

  • Random

  • The Guid Struct

  • Standard Equality Protocols

    • == and !=
    • The virtual object.Equals method
    • The static object.Equals method
    • The static object.ReferenceEquals method
    • The IEquatable<T> interface
    • When Equals and == are not equal
    • Overriding GetHashCode
    • Overriding Equals
  • Collections

    • BitArray
    • HashSet<T> and SortedSet<T>
    • Dictionaries
    • EqualityComparer<T>
  • LINQ Query

    • Deferred Execution
    • Subqueries
    • Interpreted Queries
  • Garbage Collection and Memory Consumption

    • Finalizers
    • How the GC Works
    • Managed Memory Leaks
  • Cross-Platform Diagnostics Tools

    • dotnet-counters
    • dotnet-trace
    • dotnet-dump
  • Concurrency and Asynchrony and Threading

    • Concurrency vs Multi-Threading vs Async vs Parallelism
    • Single-core vs multicore or multiprocessor machine
    • Related Data-Structures (ex: ConcurrentDictionary, Channels)
    • Sleep
    • Yield
    • Blocking
    • Spinning
    • Local versus Shared State
    • Passing Data to a Thread
    • Exception Handling
    • Foreground versus Background Threads
    • IAsyncStateMachine
    • IAsyncEnumerable
    • IAsyncDisposable
    • Synchronization Contexts
    • async void
    • The Thread Pool
      • Worker Thread vs I/O Thread
    • Tasks
      • Long-running tasks & Task.Run()
      • AggregateException
      • awaiter.GetResult() vs .Result
      • TaskCompletionSource
      • Task.Delay
      • Awaiting
      • Asynchronous call graph execution
      • ValueTask<T>
        • Precautions
      • ConfigureAwait(false)
      • Cancellation
    • Synchronization
      • Categories
        • Exclusive locking
          • lock Statement
          • Monitor.Enter and Monitor.Exit
          • Choosing the Synchronization Object
          • Deadlocks
          • Performance
          • Mutex
          • Locking and Thread Safety
        • Nonexclusive locking
          • Semaphore and SemaphoreSlim
          • Reader/Writer Locks
        • Signaling
          • AutoResetEvent
          • ManualResetEvent
          • CountdownEvent
          • Barrier Class
      • Lazy Initialization
      • Thread-Local Storage
      • Timers
      • SpinLock and SpinWait
      • Nonblocking synchronization techniques
        • Interlocked
        • memory barriers
        • volatile
      • Monitor.Wait and Monitor.Pulse
  • Stream Architecture

    • Backing stores
      • FileStream
      • NetworkStream
      • MemoryStream
      • PipeStream
        • Named pipes
        • Anonymous pipes
    • Decorators
      • BufferedStream
      • DeflateStream
      • GZipStream
      • CryptoStream
    • Adapters
      • TextReader
      • TextWriter
      • StreamReader
      • StreamWriter
      • StringReader
      • StringWriter

    image

    • Thread Safety
    • File and Directory class vs FileInfo and DirectoryInfo
    • Memory-Mapped Files
  • Network Architecture

    image

    • URIs
    • WebClient
    • HttpClient
    • HttpListener
    • TCP and UDP
  • Serialization Engines

    • XmlSerializer
    • JsonSerializer
    • The data contract serializer
    • The binary serializer
  • Assemblies

    • The Assembly Manifest
    • Resources and Satellite Assemblies
    • assembly loading
    • Assembly resolution
    • Assembly Load Contexts
    • AssemblyDependencyResolver
  • Reflection and Metadata

    • GetType Method vs typeof Operator
    • Obtaining a Type
      • Array types
      • Nested types
    • Type Names
    • Instantiating Types
    • Member Types
    • C# Members versus CLR Members
    • Late binding
    • Using Delegates for Performance
    • Attributes
      • Types
        • Bit-mapped
        • Custom
        • Pseudocustom
      • Properties and constructor parameters constraints
  • Dynamic Code Generation

    • Generating IL with DynamicMethod
    • Emitting Assemblies and Types
  • Dynamic Programming

    • Dynamic Language Runtime
    • Call Sites
    • Dynamic Member Overload Resolution
    • Anonymously Calling Members of a Generic Type
    • ExpandoObject
  • Cryptography

    • Hash Algorithms
    • Hashing Passwords
    • Symmetric Encryption
    • Public-Key Encryption and Signing
  • Parallel Programming

    • Channel
    • Data parallelism and task parallelism
    • PLINQ
    • The Parallel Class
    • Task Parallelism
    • Concurrent Collections
    • BlockingCollection<T>
  • Span<T> and Memory<T>

    • Spans and Slicing
    • Forward-Only Enumerators
  • Native and COM Interoperability

    • Calling into Native DLLs
    • The Purpose of COM
  • Regular Expressions

    • Compiled Regular Expressions
    • Character Escapes
    • Character Sets
    • Quantifiers
  • The Roslyn Compiler

    • Roslyn Architecture
      • Parsing code into syntax trees (the syntactic layer)
      • Binding identifiers to symbols (the semantic layer)
      • Emitting Intermediate Language (IL)

領域驅動設計(DDD)

  • Problem-Domain
  • Solution-Domain
  • Strategic Design
    • Ubiquitous Language
    • Bounded Context
    • Sub-domains
  • Tactical Design
    • Aggregate Root & Aggregate
    • Value-Object
    • Domain Services
    • Application Services
    • Domain Events
    • Context Mapping
    • Integration between BCs (Messaging, RPC, ...)
    • Entity Persistence
  • Patterns
    • Factory
    • Repository
    • Unit of Work
    • Event Sourcing
    • CQRS

Entity Framework

  • Change-Tracker
  • Inheritance (TPT, TPH)
  • Migrations
  • Code-First vs Database-First
  • Database-Provider mechanisms (SQL-Server, PostgreSQL, SQLite, In-Memory, ...)
  • Fluent-API
  • SaveChanges(), When & Why?
  • Transaction Management
  • DbContext Lifetime
  • Value-Converters

問題

Async/Concurrency/Threading

  • Concurrency vs Multi-Threading vs Async vs Parallelism
  • Data-Structures
    • ConcurrentDictionary
    • ConcurrentQueue
    • Channels
  • Async & Task Internals
    • At least, how many threads are needed to run an async task?
    • GetAwaiter().GetResult() vs .Result
    • Task vs ValueTask
    • Task.WhenAll & Task.WhenAny
    • FooAsync.Wait() & FooAsync.WaitAsync()
    • Why is async void bad? When do we have to use it?
    • Task.Run
      • What does it do?
      • Does Task.Run() create a new Thread?!
      • Exception-Handling in Fire & Forget scenarios
    • Thread.Sleep vs Task.Delay
    • Long-running threads (ThreadPool effects, Implementation via TaskFactory)
    • ExecutionContext vs SynchronizationContext (aspnetcore breaking changes ?)
    • AsyncLocal
    • Asynchronous design patterns like AsyncLazy
    • CancellationToken
      • Usages
      • Creating a cancellation-token using CancellationTokenSource
      • Canceling a CPU-Bound Task
      • How can we timeout an async task after some time using CancellationTokens?
    • IAsyncStateMachine
      • What's that?
      • How does it work internally?
    • IAsyncEnumerable
    • IAsyncDisposable
      • What's that?
      • Where do we need that?
  • Locking
    • Ways
      • lock keyword
      • Monitor.Enter
      • Semaphore
      • Semaphore-Slim
    • Strategies
      • Optimistic
      • Pessimistic
  • ThreadPool
    • What's thread-pool?
    • Why should we use that?
    • How can we run a piece of code on a thread-pool thread? (ThreadPool.QueueUserWorkItem)

DDD

  • What's Problem-Domain?
  • What's Solution-Domain?
  • Strategic Design
    • What's Ubiquitous Language?
    • What's Bounded Context?
    • What are DDD sub-domains?
      • What's Core domain?
      • What's Generic domain?
      • What's Supporting domain?
  • Tactical Design
    • What's Aggregate?
    • What's Value-Object?
      • Can we use C# 9 records as Value-Objects?
      • Ask for some examples of Value-Objects
      • How can we persist Value-Objects?
    • Domain Services
      • What's a domain-service?
      • How it's different from application-services?
    • Domain Events
      • What is domain-event?
      • Where we use them?
      • How to raise them?
    • Context Mapping
      • What is context-mapping?
      • What are the different context-mapping patterns?
        • Open/Host Service
        • Conformist
        • Anticorruption-Layer
        • Shared-Kernel
        • Customer/Supplier
        • Partnership
        • Published Language
        • Separate Ways
      • What's Upstream and Downstream?
    • Integration between BCs (messaging, RPC, ...)
    • Entity Persistence
      • What's persistence-ignorance?
  • Patterns
    • Factories
    • Repositories
      • What's repository?
      • What's unit-of-work?
      • Generic repository or Explicit repositories?
    • Event Sourcing
      • What's event-sourcing?
      • What are streams in event-sourcing?
      • When should we delete events from the stream?
    • CQRS
      • What's CQRS?
      • When should we do that?
      • How to synchronize Command and Query databases?

.NET

  • Common Language Runtime

    • Provides essential runtime services such as automatic memory management and exception handling
    • The word common refers to the fact that the same runtime can be shared by other managed
      programming languages, such as F#, Visual Basic, and Managed C++
    • C# is called a managed language because it compiles source code into managed code,
      which is represented in Intermediate Language (IL)
    • The CLR converts the IL into the native code of the machine, such as X86 or X64,
      usually just prior to execution. This is referred to as Just-In-Time (JIT) compilation
    • The container for managed code is called an assembly. An assembly contains not only IL,
      but type information (metadata)
  • Frameworks and Base Class Libraries

    • The Base Class Libraries (BCL) sit atop the CLR, providing features useful to any kind of application
      (such as collections, XML/JSON, input/output [I/O], networking, serialization, and parallel programming)

    • Sitting atop the BCL are application framework layers, which provide the APIs for a user interface
      paradigm (such as ASP.NET Core for a web application, or Windows Presentation Foundation
      [WPF] for a rich-client application)

      image

    • .NET Standard is not a framework; it’s merely a specification describing a minimum baseline of functionality
      (types and members) that guarantees compatibility with a certain set of frameworks. The concept is similar
      to C# interfaces: .NET Standard is like an interface that concrete types (frameworks) can implement.

      • Reference Assemblies
  • Value Types

    • All numeric types, the char type, and the bool type as well as custom struct and enum types
    • The content of a value-type variable or constant is simply a value
    • The assignment of a value-type instance always copies the instance
    • Value-type instances occupy precisely the memory required to store their fields
    • Value-type instances (and object references) live wherever the variable was declared. If the instance
      was declared as a field within a class type, or as an array element, that instance lives on the heap and
      if it appears as a parameter or local variable, it will reside on the stack
  • Reference Types

    • All class, array, delegate, and interface types and string type
    • Having two parts
      • An object
      • The reference to that object
    • Assigning a reference-type variable copies the reference, not the object instance
    • Require separate allocations of memory for the reference and object. The object consumes as many bytes
      as its fields, plus additional administrative overhead. The precise overhead is intrinsically private to
      the implementation of the .NET runtime, but at minimum, the overhead is eight bytes, used to store a key
      to the object’s type as well as temporary information such as its lock state for multithreading and a flag
      to indicate whether it has been fixed from movement by the garbage collector. Each reference to an object
      requires an extra four or eight bytes, depending on whether the .NET runtime is running on a 32- or 64-bit
      platform
  • double Versus decimal

    • double is useful for scientific computations (such as computing spatial coordinates)
      • float and double internally represent numbers in base 2. For this reason, only numbers expressible
        in base 2 are represented precisely
    • decimal is useful for financial computations and values that are man-made rather than the result of
      real-world measurements
      • decimal works in base 10
  • Although a Boolean value requires only one bit of storage, the runtime will use one byte of memory because
    this is the minimum chunk that the runtime and processor can efficiently work with. To avoid space
    inefficiency in the case of arrays, .NET provides a BitArray class in the System.Collections namespace
    that is designed to use just one bit per Boolean value

  • C#’s char type (aliasing the System.Char type) represents a Unicode character and occupies 2 bytes (UTF-16)

  • The elements in an array are always stored in a contiguous block of memory, providing highly efficient access

  • Stack

    • The stack is a block of memory for storing local variables and parameters. The stack logically grows and
      shrinks as a method or function is entered and exited
  • Heap

    • The heap is the memory in which objects (i.e., reference-type instances) reside
    • The heap also stores static fields
  • The in modifier

    • An in parameter is similar to a ref parameter except that the argument’s value cannot modified by the
      method (doing so generates a compile-time error). This modifier is most useful when passing a large value
      type to the method because it allows the compiler to avoid the overhead of copying the argument prior to
      passing it in while still protecting the original value from modification
  • Local method

    • Is visible only to the enclosing method
    • A benefit of local methods is that they can access the local variables and parameters of the enclosing method
    • Can appear within other function kinds, such as property accessors, constructors, or inside other local
      methods, and inside lambda expressions that use a statement block. Local methods can be iterators
      or asynchronous
  • CLR property implementation

    • C# property accessors internally compile to methods called get_XXX and set_XXX
  • CLR indexer implementation

    • Indexers internally compile to methods called get_Item and set_Item
  • new versus override

    public class BaseClass 
    {
      public virtual void Foo()
      { 
        Console.WriteLine ("BaseClass.Foo");
      }
    }
    
    public class Overrider : BaseClass
    {
      public override void Foo()
      {
        Console.WriteLine ("Overrider.Foo");
      }
    }
    
    public class Hider : BaseClass
    {
      public new void Foo()
      { 
        Console.WriteLine ("Hider.Foo");
      }
    }
    
    Overrider over = new Overrider();
    BaseClass b1 = over;
    over.Foo();             // Overrider.Foo
    b1.Foo();               // Overrider.Foo
    
    Hider h = new Hider();
    BaseClass b2 = h;
    h.Foo();                // Hider.Foo
    b2.Foo();               // BaseClass.Foo
    
  • Constructor and field initialization order

    1. From subclass to base class
      1. Fields are initialized
      2. Arguments to base-class constructor calls are evaluated
    2. From base class to subclass
      1. Constructor bodies execute
  • Copying semantics of boxing and unboxing

    • Boxing copies the value-type instance into the new object, and unboxing copies the contents of the object
      back into a value-type instance. In the following example, changing the value of i doesn’t change
      its previously boxed copy:

      int i = 3;
      object boxed = i;
      i = 5;
      Console.WriteLine (boxed); // 3
      
  • GetType Method vs typeof Operator

  • Struct

    • A struct is a value type, whereas a class is a reference type

    • A struct does not support inheritance (other than implicitly deriving from object, or more precisely,
      System.ValueType)

    • A struct is appropriate when value-type semantics are desirable

    • A struct can have all of the members that a class can, except the following

      • A parameterless constructor
      • Field initializers
      • A finalizer
      • Virtual or protected members
    • Converting a struct to an interface causes boxing. Calling an implicitly implemented member on a struct
      does not cause boxing:

      interface I { void Foo();
      }
      struct S : I { public void Foo() {} } ...
      S s = new S();
      s.Foo(); // No boxing.
      I i = s; // Box occurs when casting to interface.
      i.Foo();
      
    • Ref Structs

      • To ensure that it can only ever reside on the stack
      • Introduced mainly for the benefit of the Span<T> and ReadOnly Span<T> structs
      • Ref structs cannot partake in any C# feature that directly or indirectly introduces the possibility
        of existing on the heap
        • Lambda expressions
        • iterators
        • asynchronous functions
        • Cannot appear inside non-ref structs
        • Cannot implement interfaces (because this could result in boxing)
  • Friend Assemblies

    • Expose internal members to other friend assemblies
  • Reimplementing an Interface in a Subclass

    public interface IUndoable { void Undo(); }
    public class TextBox : IUndoable {
    void IUndoable.Undo() => Console.WriteLine ("TextBox.Undo"); }
    public class RichTextBox : TextBox, IUndoable {
    public void Undo() => Console.WriteLine ("RichTextBox.Undo"); }
    
    RichTextBox r = new RichTextBox();
    r.Undo();// RichTextBox.Undo
    ((IUndoable)r).Undo();   // RichTextBox.Undo
    

    Assuming the same RichTextBox definition, suppose that TextBox implemented Undo implicitly:

    public class TextBox : IUndoable {
    public void Undo() => Console.WriteLine ("TextBox.Undo"); }
    
    RichTextBox r = new RichTextBox();
    r.Undo();// RichTextBox.Undo
    ((IUndoable)r).Undo();// RichTextBox.Undo
    ((TextBox)r).Undo();// TextBox.Undo
      
    
  • Enum Type-Safety Issues

    • Use Enum.IsDefined
  • Generic

    • Avoid casting and boxing

    • Open generic types do not exist at runtime: open generic types are closed as part of compilation
      (see also Generics in the Run Time)

    • Static data is unique for each closed type

    • Constraints

      where T : base-class // Base-class constraint
      where T : interface    // Interface constraint
      where T : class  // Reference-type constraint
      where T : class?  // Nullable Reference-type constraint
      where T : struct  // Value-type constraint (excludes Nullable types)
      where T : unmanaged // Unmanaged constraint
      where T : new() // Parameterless constructor constraint
      where U : T // Naked type constraint
      where T : notnull // Non-nullable value type, or from C# 8 
                        // a non-nullable reference type.
      
    • Covariance

      • Assuming A is convertible to B, X has a covariant type parameter if X<A> is convertible to X<B>
        (convertible via an implicit reference conversion— such as A subclassing B, or A implementing B)

      • For instance, type IFoo<T> has a covariant T if the following is legal:

          IFoo<string> s = ...;
          IFoo<object> b = s;
        
      • Interfaces and delegates permit covariant type parameters, but classes do not because a class can implement
        both Covariance and Contravariance interfaces

      • B[] can be cast to A[] if B subclasses A (and both are reference types)

        Bear[] bears = new Bear[3];
        Animal[] animals = bears;  // OK
        

        The downside of this reusability is that element assignments can fail at runtime:

        animals[0] = new Camel(); // Runtime error
        
      • Declaring a covariant type parameter

        • Type parameters on interfaces and delegates can be declared covariant by marking them with
          the out modifier

        • Ensures that, unlike with arrays, covariant type parameters are fully type-safe

        • The out modifier on T indicates that T is used only in output positions
          (e.g., return types for methods)

        • The compiler will generate an error if you use a covariant type parameter in an input position
          (e.g., a parameter to a method or a writable property)

            public interface IPoppable<out T> { T Pop(); }
            var bears = new Stack<Bear>();
            bears.Push (new Bear());
            // Bears implements IPoppable<Bear>. We can convert to IPoppable<Animal>:
            IPoppable<Animal> animals = bears; // Legal
            Animal a = animals.Pop();
          
    • Contravariance

      • assuming that A allows an implicit reference conversion to B, Contravariance is when you can convert
        in the reverse direction—from X<B> to X<A>

      • Is supported if the type parameter appears only in input positions and is designated with the in modifier

          public interface IPushable<in T> { void Push (T obj); }
          IPushable<Animal> animals = new Stack<Animal>();
          IPushable<Bear> bears = animals; // Legal
          bears.Push (new Bear());
        
  • Delegate

    • Parameter compatibility

      When you call a method, you can supply arguments that have more specific types than the parameters
      of that method. This is ordinary polymorphic behavior. For the same reason, a delegate can have more
      specific parameter types than its method target. This is called Contravariance:

      delegate void StringAction(string s);
      class Test
      {
          static void Main()
          {
              StringAction sa = new StringAction(ActOnObject); sa("hello");
          }
          static void ActOnObject(object o) => Console.WriteLine(o); // hello
      }
      
    • Return type compatibility

      If you call a method, you might get back a type that is more specific than what you asked for.
      This is ordinary polymorphic behavior. For the same reason, a delegate’s target method might return
      a more specific type than described by the delegate. This is called Covariance:

      delegate object ObjectRetriever();
      class Test
      {
          static void Main()
          {
              ObjectRetriever o = new ObjectRetriever(RetrieveString);
              object result = o();
              Console.WriteLine(result);  // hello 
          }
          static string RetrieveString() => "hello";
      }
      
    • Generic delegate type

      delegate TResult Func<out TResult>();
      // allowing:
      Func<string> x = ...; 
      Func<object> y = x;
      
      delegate void Action<in T> (T arg);
      // allowing:
      Action<object> x = ...;
      Action<string> y = x;
      
  • Events

    • Three things happen under the hood when you declare an event as follows:

      public class Broadcaster
      {
          public event PriceChangedHandler PriceChanged;
      }
      
      • First, the compiler translates the event declaration into something close to the following:

        PriceChangedHandler priceChanged; // private delegate
        public event PriceChangedHandler PriceChanged
        {
            add { priceChanged += value; }
            remove { priceChanged -= value; }
        }
        
      • Second, the compiler looks within the Broadcaster class for references to PriceChanged that perform operations
        other than += or -=, and redirects them to the underlying priceChanged delegate field.

      • Third, the compiler translates += and -= operations on the event to calls to the event’s add and remove
        accessors.

    • If remove the event keyword and use PriceChanged as a delegate, subscribers could do the following

      • Replace other subscribers by reassigning PriceChanged (instead of using the += operator).
      • Clear all subscribers (by setting PriceChanged to null).
      • Broadcast to other subscribers by invoking the delegate.
    • Standard Event Pattern

  • Lambda Expressions

    • The compiler immediately converts the lambda expression to either of the following:

      • A delegate instance
      • An expression tree, of type Expression<TDelegate>, representing the code inside the lambda expression
        in a traversable object model. This allows the lambda expression to be interpreted later at runtime
    • Internally, the compiler resolves lambda expressions of this type by writing a private method and then
      moving the expression’s code into that method:

      delegate int Transformer (int i);
      Transformer sqr = x => x * x;
      Console.WriteLine (sqr(3)); // 9
      
    • A lambda expression that captures variables is called a Closure

    • Outer variables referenced by a lambda expression are called captured variables

    • Captured variables are evaluated when the delegate is actually invoked,
      not when the variables were captured

      int factor = 2;
      Func<int, int> multiplier = n => n * factor; factor = 10;
      Console.WriteLine(multiplier(3));  // 30
      
    • Lambda expressions can themselves update captured variables

      int seed = 0;
      Func<int> natural = () => seed++;
      Console.WriteLine(natural());// 0 
      Console.WriteLine(natural());// 1 
      Console.WriteLine(seed);// 2 
      
    • A local variable instantiated within a lambda expression is unique per invocation of the delegate instance

    • Capturing is internally implemented by “hoisting” the captured variables into fields of a private class.
      When the method is called, the class is instantiated and lifetime-bound to the delegate instance

    • Capturing iteration variables

    • Lambda Expressions Versus Local Methods

    • Anonymous and local methods capture outer variables in the same way lambda expressions do

  • try Statements and Exceptions

    • Checking for preventable errors is preferable to relying on try/catch blocks because exceptions are
      relatively expensive to handle, taking hundreds of clock cycles or more
    • Exception filters
    • The finally Block
    • The using statement
    • If we replaced throw with throw ex, the example would still work, but the StackTrace property of the
      newly propagated exception would no longer reflect the original error.
  • Enumeration and Iterators

    • The compiler converts iterator methods into private classes that implement IEnumerable<T>
      and/or IEnumerator<T>. The logic within the iterator block is “inverted” and spliced into the MoveNext
      method and Current property on the compilerwritten enumerator class. This means that when you call an
      iterator method, all you’re doing is instantiating the compilerwritten class; none of your code actually
      runs! Your code runs only when you start enumerating over the resultant sequence, typically with a
      foreach statement.
    • yield break and yield return
    • A yield return statement cannot appear in a try block that has a catch clause Nor can yield return appear
      in a catch or finally block.
      • These restrictions are due to the fact that the compiler must translate iterators into ordinary classes
        with MoveNext, Current, and Dispose members, and translating exception handling blocks would create
        excessive complexity
  • The Array Class

  • Nullable<T> Struct

    • Operator Lifting
      • Equality operators
      • Relational operators
  • Nullable Reference Types

  • Extension Methods

  • Anonymous Types

  • Tuple and ValueTuple

  • Patterns

    • Property Patterns
    • Tuple Patterns
    • Positional Patterns
    • var Patterns
    • Constant Patterns
  • Caller Info Attributes

    • CallerMemberName
    • CallerFilePath
    • CallerLineNumber
  • Dynamic Binding

  • Unsafe Code and Pointers

    • Pointer types are primarily useful for interoperability with C APIs, but you also can use them for
      accessing memory outside the managed heap or for performance-critical hotspots
    • The stackalloc Keyword
  • Preprocessor Directives

    • Conditional Attributes
  • Comparing Strings

    • Equality comparison
    • order comparison
      • Ordinal versus culture comparison
  • StringBuilder

  • Text Encodings and Unicode

  • Dates and Times

    • TimeSpan
    • DateTime and DateTimeOffset
    • Time Zones
    • Alternatives
  • BigInteger

  • Complex

  • Random

  • The Guid Struct

  • Standard Equality Protocols

    • == and !=
    • The virtual object.Equals method
    • The static object.Equals method
    • The static object.ReferenceEquals method
    • The IEquatable<T> interface
    • When Equals and == are not equal
    • Overriding GetHashCode
    • Overriding Equals
  • Collections

    • BitArray
    • HashSet<T> and SortedSet<T>
    • Dictionaries
    • EqualityComparer<T>
  • LINQ Query

    • The compiler processes a Query Expression by translating it into fluent syntax. It does this in a fairly
      mechanical fashion—much like it translates foreach statements into calls to GetEnumerator and MoveNext.
      This means that anything you can write in query syntax you can also write in fluent syntax
    • Deferred Execution
      • How Deferred Execution Works
      • Captured Variables
    • Subqueries
      • Subqueries and Deferred Execution
    • Interpreted Queries
  • Expression Trees

    • The Expression DOM
  • Garbage Collection and Memory Consumption

    • Finalizers
    • How the GC Works
      • Generational collection
      • The Large Object Heap
      • Workstation versus server collection
      • Background collection
      • Memory Pressure
      • Array Pooling
      • Sync vs Async resource release (await using vs using) eg: DisposeAsync
    • Managed Memory Leaks
      • Timers
      • Event handlers and Weak References
  • Cross-Platform Diagnostics Tools

    • dotnet-counters
    • dotnet-trace
    • dotnet-dump
  • Concurrency and Asynchrony

    • On a single-core computer, the operating system must allocate “slices” of time to each thread
      (typically 20 ms in Windows) to simulate concurrency, resulting in repeated blocks of x and y.
      On a multicore or multiprocessor machine, the two threads can genuinely execute in parallel
      (subject to competition by other active processes on the computer), although you still get
      repeated blocks of x and y in this example because of subtleties in the mechanism by which
      Console handles concurrent requests
    • Thread.Sleep(0) relinquishes the thread’s current time slice immediately, voluntarily handing over the
      CPU to other threads. Thread.Yield() does the same thing except that it relinquishes only to threads
      running on the same processor.
    • Blocking
      • I/O-bound versus compute-bound
      • Blocking versus spinning
    • Local versus Shared State
    • Passing Data to a Thread
      • Lambda expressions and captured variables
    • Exception Handling
      • Centralized exception handling
    • Foreground versus Background Threads
    • Signaling
    • Synchronization Contexts
    • The Thread Pool
      • Hygiene in the thread pool
    • Tasks
      • Long-running tasks
      • The CLR wraps the exception in an AggregateException in order to play well with parallel programming
        scenarios
      • awaiter.GetResult() vs .Result
      • TaskCompletionSource
      • Task.Delay is the asynchronous equivalent of Thread.Sleep
      • Awaiting
        • Upon encountering an await expression, execution (normally) returns to the caller—rather like with yield
          return in an iterator. But before returning, the runtime attaches a continuation to the awaited task,
          ensuring that when the task completes, execution jumps back into the method and continues where it left
          off. If the task faults, its exception is rethrown, otherwise its return value is assigned to the
          await expression
        • Capturing local state
      • Asynchronous call graph execution
      • ValueTask<T>
        • Precautions
      • ConfigureAwait(false)
      • Cancellation
  • Stream Architecture

    • Backing stores
    • Decorators
    • Adapters

    image

    • PipeStream
    • Named pipes

Entity Framework

  • Change-Tracker
    • What's change-tracker?
    • What's .AsNoTracking()?
    • How EF detect changes when you update a property value?
  • Inheritance (TPT, TPH)
    • What's TPT?
    • What's TPH?
  • Migrations
    • What are migrations?
    • What we achieve with them?
  • Code-First vs Database-First
    • What's code-first approach?
    • What's database-first approach?
    • How to use code-first when we have an existing database schema?
  • Database-Provider mechanisms (SQL-Server, PostgreSQL, SQLite, In-Memory, ...)
    • What are Providers in EF-Core?
    • How can we use EF-Core in unit-tests?
  • Fluent-API
    • What's fluent-api?
    • Advantages and downsides against Attributes
  • SaveChanges(), When & Why?
  • Transaction Management
    • How can we rollback a failed transaction in EF?
  • DbContext Lifetime
    • What's EF-Core's default lifetime? Do you know Why?
    • Can we use Singleton as DbContext's lifetime? Why?
  • Value-Converters
    • What are value-converters in EF?
    • What are its usages?

Object-Oriented

Programming paradigms

  • What are programming paradigms?
    • A programming paradigm is a way of conceptualizing what it means to perform computation, and how tasks that are to be carried out on a computer should be structured and organized.
    • Programming paradigm involves viewing the solution of a problem by combining Data and Algorithms in different ways

OOP Paradigms

  • What's OOP paradigms
    • A very powerful paradigm for modeling real-world phenomena in a computational model

Object-Oriented

  • What Is a Class?
  • What Is an Abstract Class?
  • What Is an Interface?
  • What Is an Object?
  • What is the difference between a class and an object?
  • What are the differences between an abstract class and an interface?
  • What are access specifiers?
  • What is Static Class?
  • What is the Static Method?
  • What are Object Oriented Principles

Object Oriented Principles

  • What are Abstraction, Encapsulation, and Information Hiding differences?
    • Abstraction is only concerned about which item should be hidden. What should (not) be hidden (or ignored) is the concern of abstraction.
    • Encapsulation is bundling of data and operations on the data into an entity called a class and is not concerned with whether the items that are bundled in an entity are hidden from other modules in the application or not.
    • Information Hiding is concerned with how an item is hidden

Abstraction

  • What's Abstraction?
    • Abstraction is a way to perform decomposition of a problem by focusing on relevant details and ignoring the irrelevant details about it in a particular context
  • what's decomposition?
    • involves analyzing a complex problem or system and breaking it down into smaller parts that are more manageable and easy to understand
  • What types of Abstraction are there?
Data Abstraction
  • What's Data Abstraction?
    • hiding the details about the data
    • lets programmers create a new data type called an abstract data type (ADT)
  • How can achieve data abstraction?
Procedural (Process,Control) Abstraction
Procedural Abstraction by Parameterization
  • What is Procedural Abstraction by Parameterization?
    • We seek generality by allowing the same mechanism to be adapted to many different contexts by providing it with information on that context
Procedural Abstraction by Specification
  • What is Procedural Abstraction by Specification?
    • We ignore the implementation details and agree to treat as acceptable any implementation that adheres to the specification

Encapsulation and Information Hiding

  • What is Encapsulation?
    • Encapsulation is simply the bundling of items together into one entity
  • What is Information Hiding?
    • Information hiding is the process of hiding implementation details that are likely to change

Inheritance

  • What's Inheritance?
    • The inheritance mechanism lets you define a new abstraction by extending an existing abstraction
    • Inheritance allows you to use varying degrees of abstraction at different levels of hierarchy
    • Inheritance is also used as a technique to implement polymorphism
  • What's Multiple Inheritance?
    • Name ambiguity
      • Inherited, different features can have the same name
      • Same features may be inherited several times
    • Impact on substitutability
      • Parent constructor calling in Diamond problem
      • Ambiguity in calling method has override in supper classes but not in descendent class
      • Overriding a method that has been inherited from several supper classes
    • Increase Complexity

Polymorphism

Ad hoc Polymorphism
Overloading Polymorphism
  • What's Overloading Polymorphism?
    • When a method or an operator has at least two definitions that work on a different type
  • Make an example
    //Method overloading
    Do()
    Do(10)
    
    //operator overloading
    var i = 1 + 1;
    var j = 1.5 + 2;
    
Coercion Polymorphism
  • What's Coercion Polymorphism?

    • When a type is implicitly converted (coerced) to another type automatically even if it was not intended explicitly
  • Make an example

    var int i = 1;
    var double d = i;
    var double d = (double)i;  
    
Universal Polymorphism
Inclusion Polymorphism
  • What's Inclusion Polymorphism?

    • When a piece of code that is written using a type works for all its subtypes
  • Make an example

    void processDetails(Person p) 
    { 
      // Write code using the formal parameter p, which is of type Person.
      // The same code will work if an object of any of the subclass of Person is passed to this method.
    } 
    /************************************client code*************************************************/ 
    Person p1 = new Person(); 
    Employee e1 = new ; 
    Customer c1 = create a Customer object; 
    processDetails(p1); // Use Person type 
    processDetails(e1); // Use Employee type, which is a subclass of Person 
    processDetails(c1); // Use Customer type, which is a subclass of Person
    
Parametric polymorphism
  • What's Parametric polymorphism?
    • Parametric polymorphism is achieved by using a type variable when writing the code, rather than using any specific type
    • It is also called “true” polymorphism because it lets you write true generic code that works for any types (related or unrelated)
  • What types of Parametric Polymorphism are there?
    • Invariant
      • Means that you can use only the type originally specified
    • Covariant
      • Enables you to use a more derived type than originally specified
    • Contravariant
      • Enables you to use a more generic (less derived) type than originally specified
Invariant Parametric polymorphism
  • What's Invariant Parametric polymorphism?

    • Means that you can use only the type originally specified
      var list = new Lis<int>();
    
Covariant Parametric polymorphism
  • What's Covariant Parametric polymorphism?

    • Enables you to use a more derived type than originally specified
      IEnumerable<Derived> enumerable1 = new List<Derived>(); // IEnumerable<out T>
      IEnumerable<Base> enumerable2 = enumerable1;
    
Contravariant Parametric polymorphism
  • What's Contravariant Parametric polymorphism?

    • Enables you to use a more generic (less derived) type than originally specified
      Action<Base> action1 = target => { ... }; //Action<in T> 
      Action<Derived> action2 = action2; 
      action2(new Derived());
    

Dispatch

  • What's Dispatching?
    • it is a way how the programming language calls a method or a function
  • What types of Dispatch are there?
    • Static Dispatch
      • Every method is known at the compile time
    • Dynamic Dispatch
      • Dynamically dispatched methods are determined at run time based on its parameter’s types

Static Dispatch

  • What's Static Dispatch?
    • Every method is known at the compile time
  • Make an example
    //classes
    interface IBar {} 
    class Bar : IBar {} 
    sealed class FooBar : Bar {} 
    
    //methods
    void Print(IBar item){Console.WriteLine("It is an IBar.");} 
    void Print(Bar item){Console.WriteLine("It is a Bar.");} 
    void Print(FooBar item){Console.WriteLine("It is a FooBar.");}
    
    //call methods
    var bar = new Bar(); 
    var foo = new FooBar(); 
    IBar ibar = new FooBar(); 
    Print(bar);
    Print(foo);
    Print(ibar);
    
    Output:
    It is a Bar.
    It is a FooBar.
    It is an IBar.
    

Dynamic Dispatch

  • What's Dynamic Dispatch?
    • Dynamically dispatched methods are determined at run time based on their parameter’s types
  • What types of Dynamic Dispatch are there?
    • Single dynamic dispatch
      • Single ones use just one parameter to select a method
      • Satisfy by overriding
    • Multiple dynamic Dispatch
      • The multiple ones can take advantage of as many parameters they want
      • Satisfy by DLR (Dynamic Language Runtime)
Single dynamic dispatch
  • What's Single dynamic dispatch?
    • Single ones use just one parameter to select a method
  • Make an example
    class SurveyBase{ public virtual void DoSurvey(){...} } 
    class Survey : SurveyBase{ public override void DoSurvey() {...} } 
    /*****************************Client Code**************************************/ 
    SurveyBase base = new Survey(); 
    base.DoSurvey(); // Survey.DoSurvey will be called
    
Multiple dynamic dispatch
  • What's Multiple dynamic Dispatch?
    • The multiple ones can take advantage of as many parameters they want
  • Make an example
    //classes
    interface IBar {} 
    class Bar : IBar {} 
    sealed class FooBar : Bar {} 
    //methods
    void Print(IBar item){Console.WriteLine("It is an IBar");} 
    void Print(Bar item){Console.WriteLine("It is a Bar");} 
    void Print(FooBar item){Console.WriteLine("It is a FooBar");}
    //call methods, 
    var bar = new Bar();
    var foo = new FooBar();
    IBar ibar = new FooBar();
    IBar[] items = { bar, foo, ibar };
    
    foreach (var item in items) 
    { 
      Print(item); 
    }
    foreach (dynamic item in items) 
    { 
      Print(item);
    }
    
    Output:
    It is an IBar.
    It is an IBar.
    It is an IBar.
    
    It is a Bar.
    It is a FooBar.
    It is a FooBar.
    

Method Hiding and Overriding

  • What's Method Hiding?
    • Method hiding means Subclass has defined a class method with the same signature as a class method in the superclass. In that case, the method of the superclass is hidden by the subclass.
  • What's Method Overriding?
    • The ability of a subclass to override a method allows a class to inherit from a superclass whose behavior is "close enough" and then to modify behavior as needed.

參考

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章