This article is a detailed commentary on another article . Usually I walk by, but now for some reason I was hurt.
That article was a near-perfect collection of misconceptions in a vacuum. Moreover, they (misconceptions) are quite popular and are constantly found in various blogs and collections of "99 interview questions", "how to get an interview for a junior" or in this case "C # cheat sheet".
? , , , . , . , , . , β , , .
, . ( , ) . :
β ECMA 334 ( 5).
β , ECMA 334, . dotnet, - MSDN.
β ( ) MSDN.
β MSDN, Wikipedia , , .
β , . , , - , ))
... !
(value vs reference types)
: (reference type) (heap), (value types) β .
? β , . , , , .
: 2 «», , , . β , (fixed) , . β 16.1 Structs/General, , :
However, unlike classes, structs are value types and do not require heap allocation
, ( ).
: , , . , , , .
( ) , . . , , @VladD-exrabbit : https://github.com/dotnet/runtime/issues/11192
value reference ?
( Structs struct ):
16.4.2 Value semantics
- A variable of a struct type directly contains the data of the struct, whereas a variable of a class type contains a reference to an object that contains the dataβ¦
, , β . , ( ):
struct Node
{
int data;
Node next; // error, Node directly depends on itself
}
// is an error because Node contains an instance field of its own type. Another example
struct A { B b; }
struct B { C c; }
struct C { A a; }
With classes, it is possible for two variables to reference the same objectβ¦
( ) , .
, , . (16.4.3 Inheritance) , (16.4.4 Assignment β ), 16.4.5 Default values β , 16.4.6 Boxing and unboxing β , . 16.4.7 Meaning of this, 16.4.8 Field initializers, 16.4.9 Constructors, 16.4.10 Static constructors, 16.4.11 Automatically implemented properties.
, . , , ( ), , β , , β .
stack vs heap
(1): , .
? , , , . , , , . , .
: heap . stack unsafe- stackalloc, .
: ( ), β ( , ). ( , ) , , .
:
EDITBIN.EXE /STACK:<stacksize> file.exe
β new Thread().
, , , , , . , , . unsafe offheap-.
: , .
/
: () () β .
? β . .
:
10.2.5 Value parameters
A parameter declared without a ref or out modifier is a value parameter.
10.2.6 Reference parameters
A parameter declared with a ref modifier is a reference parameter.
10.2.7 Output parameters
A parameter declared with an out modifier is an output parameter.
, . , , (/) , . Output parameter , ref-, . , .
Java 8- ( - , - ), ++ ( C, ) C#. , : Java, C++, C#.
: Java , ( C#, ) C++ β , ( /). C# : . .
P.S.: in-. ( , ), ref- (readonly ref) .
string β
: , .
:
9.2.5 The string type
The string type is a sealed class type that inherits directly from object. Instances of the string class represent Unicode character strings.
Values of the string type can be written as string literals (Β§7.4.5.6).
The keyword string is simply an alias for the predefined class System.String
, .
: , ( ) . , ? , , .
?
1. (immutable) (sealed) . , . ? , .
2. ==, , , . ? .
const vs readonly
:
Β· const - =>
Β· readonly -
:
12.20 Constant expressions
A constant expression is an expression that shall be fully evaluated at compile-time
Β« Β», Β« Β» ( , ).
15.5.3 Readonly fields
15.5.3.1 General When a field-declaration includes a readonly modifier, the fields introduced by the declaration are readonly fields. Direct assignments to readonly fields can only occur as part of that declaration or in an instance constructor or static constructor in the same class.
, . (12 15)? : β , β . .
:
15.5.3.3 Versioning of constants and static readonly fields
Constants and readonly fields have different binary versioning semantics. When an expression references a constant, the value of the constant is obtained at compile-time, but when an expression references a readonly field, the value of the field is not obtained until run-time.
. readonly- ( ) β . , -, , , readonly- .
: .NET Core 3 readonly- , , . , , .
ref out
-«»: ref out new class struct
: ( )
out ref, ,
, , «», , .
,
:
if (Evt != null)
Evt("hello");
: 15.8.2 Field-like events
EventHandler handler = Click;
if (handler != null)
handler(this, e);
, , .
P.S.: C# Evt?.Invoke("hello");
Finalizer (destructor) ~
(1): ~Foo() «» Foo
:
15.13 Finalizers
[Note: In an earlier version of this standard, what is now referred to as a "finalizer" was called a
"destructor". Experience has shown that the term "destructor" caused confusion and often resulted to incorrect expectations, especially to programmers knowing C++. In C++, a destructor is called in a determinate manner, whereas, in C#, a finalizer is not. To get determinate behavior from C#, one should use Dispose. end note]
P.S.: , @rstm-sf.
(2): , garbage collector
? .
:
An instance becomes eligible for finalization when it is no longer possible for any code to use that instance. Execution of the finalizer for the instance may occur at any time after the instance becomes eligible for finalization (Β§8.9).
, .
: , SuppressFinalize . - . . GC.SuppressFinalize, . , IDisposable .
(3): .Net,
: , . , , :
myObj.GetType().GetMethod("Finalize",
BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly)
.Invoke(myObj, null);
, ( ).
Singletone
: lock
? , , .
, .
static Singleton singletonInstance;
static readonly Object syncRoot = new Object();
public static Singleton GetInstance()
{
if(singletonInstance == null)
lock(syncRoot)
if(singletonInstance == null)
singletonInstance = new Singleton();
return singletonInstance;
}
double checked locking, . , , .
, . , , ( , /). , volatile MemoryBarrier().
: . :
public static Singleton Instance { get; } = new Singleton();
, - . , 99% . , .
, , β Lazy<T>, .
, , 1% , , :
static readonly Lazy<Singleton> lazy = new Lazy<Singleton>(() => new Singleton());
public static Singleton Instance => lazy.Value;
And yes, this was also already on HabrΓ© , with a bunch of comments.
PS: and it just so happened that today such a detailed article (18+) was posted on HabrΓ© !
It seems that everything is under the article. I obviously forgot something, or wrote it wrong, but there are comments for this, let it be a shit!