Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

The documentation of the order of static constructors is wrong. #41629

Open
steinbitglis opened this issue Jul 2, 2024 · 2 comments
Open

The documentation of the order of static constructors is wrong. #41629

steinbitglis opened this issue Jul 2, 2024 · 2 comments
Assignees
Labels
doc-bug Problem with the content; needs to be fixed [org][type][category] dotnet-csharp/svc fundamentals/subsvc okr-health Content-health KR: Concerns article defects/freshness or build warnings. Pri1 High priority, do before Pri2 and Pri3 📌 seQUESTered Identifies that an issue has been imported into Quest.

Comments

@steinbitglis
Copy link

steinbitglis commented Jul 2, 2024

Type of issue

Other (describe below)

Description

The following bit seems wrong.

  1. Base static constructors run. Any static constructors, starting with Object.Object through each base class to the direct base class.
  2. The static constructor runs. The static constructor for the type runs.

As I will demonstrate, in cases where the members of the base class is not accessed by the deriving class, the deriving class constructor will run before the base constructor.

using static System.Console;

class BaseClass {
    static protected int c = 1;
    static BaseClass() => WriteLine($"{c++}. Static   constructor of *BaseClass*    called.");
    public BaseClass() => WriteLine($"{c++}. Instance constructor of *BaseClass*    called.");
}
class DerivedClass : BaseClass {
    static DerivedClass()          => WriteLine($"{c++}. Static   constructor of  DerivedClass  called.");
    public DerivedClass() : base() => WriteLine($"{c++}. Instance constructor of  DerivedClass  called.");
}

public static class C {
    public static int c = 1;
}
class BaseClass2 {
    static BaseClass2() => WriteLine($"{C.c++}. Static   constructor of *BaseClass2*   called.");
    public BaseClass2() => WriteLine($"{C.c++}. Instance constructor of *BaseClass2*   called.");
}
class DerivedClass2 : BaseClass2 {
    static DerivedClass2()          => WriteLine($"{C.c++}. Static   constructor of  DerivedClass2 called.");
    public DerivedClass2() : base() => WriteLine($"{C.c++}. Instance constructor of  DerivedClass2 called.");
}

public class Program {
    public static void Main() {
        var instance = new DerivedClass();
        WriteLine();
        var instance2 = new DerivedClass2();
    }
}

The results are different in the two cases:

1. Static   constructor of *BaseClass*    called.
2. Static   constructor of  DerivedClass  called.
3. Instance constructor of *BaseClass*    called.
4. Instance constructor of  DerivedClass  called.

1. Static   constructor of  DerivedClass2 called.
2. Static   constructor of *BaseClass2*   called.
3. Instance constructor of *BaseClass2*   called.
4. Instance constructor of  DerivedClass2 called.

Page URL

https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/static-constructors

Content source URL

https://github.com/dotnet/docs/blob/main/docs/csharp/programming-guide/classes-and-structs/static-constructors.md

Document Version Independent Id

ac4f6361-70a7-fb43-101e-c12044f60896

Article author

@BillWagner

Metadata

  • ID: aa3ed1c5-1f79-9234-beec-b5771c3fb3c0
  • Service: dotnet-csharp
  • Sub-service: fundamentals

Associated WorkItem - 275698

@issues-automation issues-automation bot added dotnet-csharp/svc fundamentals/subsvc Pri1 High priority, do before Pri2 and Pri3 labels Jul 2, 2024
@dotnet-bot dotnet-bot added ⌚ Not Triaged Not triaged labels Jul 2, 2024
@BillWagner BillWagner added the doc-bug Problem with the content; needs to be fixed [org][type][category] label Jul 2, 2024
@dotnet-bot dotnet-bot removed the ⌚ Not Triaged Not triaged label Jul 2, 2024
@BillWagner BillWagner self-assigned this Jul 2, 2024
@BillWagner BillWagner added the 🗺️ reQUEST Triggers an issue to be imported into Quest. label Jul 2, 2024
@BillWagner
Copy link
Member

Here's a related interesting bit:

using static System.Console;

class BaseClass {
    static protected int c = 1;
    static BaseClass() => WriteLine($"{c++}. Static   constructor of *BaseClass*    called.");
    public BaseClass() => WriteLine($"{c++}. Instance constructor of *BaseClass*    called.");
}
class DerivedClass : BaseClass {
    static DerivedClass()          => WriteLine($"{c++}. Static   constructor of  DerivedClass  called.");
    public DerivedClass() : base() => WriteLine($"{c++}. Instance constructor of  DerivedClass  called.");
}

public static class C {
    public static int c = 1;
}
class BaseClass2 {
    static BaseClass2() => WriteLine($"{C.c++}. Static   constructor of *BaseClass2*   called.");
    public BaseClass2() => WriteLine($"{C.c++}. Instance constructor of *BaseClass2*   called.");
}
class DerivedClass2 : BaseClass {
    static DerivedClass2()          => WriteLine($"{C.c++}. Static   constructor of  DerivedClass2 called.");
    public DerivedClass2() : base() => WriteLine($"{C.c++}. Instance constructor of  DerivedClass2 called.");
}

public class Program {
    public static void Main() {
        var instance = new DerivedClass();
        WriteLine();
        var instance2 = new DerivedClass2();
    }
}

The output is:

1. Static   constructor of *BaseClass*    called.
2. Static   constructor of  DerivedClass  called.
3. Instance constructor of *BaseClass*    called.
4. Instance constructor of  DerivedClass  called.

1. Static   constructor of  DerivedClass2 called.
5. Instance constructor of *BaseClass*    called.
2. Instance constructor of  DerivedClass2 called.

The static ctor for BaseClass isn't required to be run at all. No static members have been accessed.

@steinbitglis
Copy link
Author

Here's a related interesting bit:
...
The static ctor for BaseClass isn't required to be run at all. No static members have been accessed.

I think you just mixed up BaseClass and BaseClass2 there.

@dotnet-policy-service dotnet-policy-service bot added the okr-health Content-health KR: Concerns article defects/freshness or build warnings. label Jul 2, 2024
@sequestor sequestor bot added 📌 seQUESTered Identifies that an issue has been imported into Quest. and removed 🗺️ reQUEST Triggers an issue to be imported into Quest. labels Jul 3, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
doc-bug Problem with the content; needs to be fixed [org][type][category] dotnet-csharp/svc fundamentals/subsvc okr-health Content-health KR: Concerns article defects/freshness or build warnings. Pri1 High priority, do before Pri2 and Pri3 📌 seQUESTered Identifies that an issue has been imported into Quest.
Projects
Status: 🔖 Ready
Development

No branches or pull requests

3 participants