2

I've read this thread "When is a static constructor called in C#" including the Programming Guide.

But is there any way to use a static constructor WITH a parameter?

I see the problem, that the static constructor is invoked bevor the first instance is created. I search for any smart solution/workaraound.

Here an example:

public class Bus
{
    protected static readonly DateTime globalStartTime;
    protected static readonly int FirstBusNumber;

    protected int RouteNumber { get; set; }

    static Bus(/*int firstBusNumber*/)//Error if uncomment: The static constructor must be parameterless
    {
        //FirstBusNumer = firstBusNumber;
        globalStartTime = DateTime.Now;
        Console.WriteLine($"The First Bus #{FirstBusNumber} starts at global start time {globalStartTime.ToLongTimeString()}");
    }
    public Bus(int routeNum) 
    {
        RouteNumber = routeNum;
        Console.WriteLine($"Bus #{RouteNumber} is created.");
    }
    public void Drive()
    {
        var elapsedTime = DateTime.Now - globalStartTime;
        Console.WriteLine("{0} is starting its route {1:N2} minutes after the first Bus #{2}.",
           RouteNumber,
           elapsedTime.TotalMilliseconds,
           FirstBusNumber
        );
    }
}

...

var bus1 = new Bus(71);
var bus2 = new Bus(72);

bus1.Drive();
System.Threading.Thread.Sleep(25);
bus2.Drive();

System.Console.WriteLine("Press any key to exit.");
System.Console.ReadKey();

Notice: Following code is not an acceptable solution.

public Bus(int routeNum)
{
    if (FirstBusNumber < 1)
       FirstBusNumber = routeNum;
    // ... 
}
AustinWBryan
  • 3,249
  • 3
  • 24
  • 42
Syrlia
  • 154
  • 2
  • 14
  • 1
    Can you explain the use case of why you need a static constructor with a parameter? – Chetan Jul 30 '18 at 09:22
  • 1
    please can you explain why you feel the need for a parameter on a static constructor.. if you read the info you will understand more why it wouldnt have one – BugFinder Jul 30 '18 at 09:22
  • 1
    I don't see the need for the `firstBusNumber` parameter. I also don't see the need for the `globalStartTime` field. Why it's initialized from the static constructor? This should be done from a method in your business logic(i.e. the first bus starts). – Tim Schmelter Jul 30 '18 at 09:23
  • This Example has nothing to do with my project. In my project i have a controller which need a ConnectionObject. The object is the same for all and never changes. – Syrlia Jul 30 '18 at 09:26
  • Well, the static constructor isn´t really a constructor, it´s just some code that gets executed if any logic within your class will ever be executed. In particular no instance is created by the static constructor, all it does is to wrap a few lines of code that should be executed when the first access to the class is made. – MakePeaceGreatAgain Jul 30 '18 at 09:27
  • 2
    @Syrlia: then you should give this connection-object via normal constructor. You can use a singleton if desired(because it's same for all). – Tim Schmelter Jul 30 '18 at 09:27
  • Sounds like you´re actually trying to solve something completely different, but you think the static constructor is what you need - which it apparently is not. So what is the actual problem you´re trying to solve? – MakePeaceGreatAgain Jul 30 '18 at 09:31
  • @TimSchmelter: See at my notice. I want avoid use anything similar. Do you have a better idea? Relating to Singleton: I thought 'never ever use a singleton'. – Syrlia Jul 30 '18 at 09:32
  • 1
    Who sais "never use a singleton"? That pattern exists for some reasons. Anyway everything is better the a static constructor - even a singleton. – MakePeaceGreatAgain Jul 30 '18 at 09:35
  • Then i'll use a Singleton instead. Thanks. – Syrlia Jul 30 '18 at 09:42
  • 1
    Notice: Next time, could you explain a bit more as to *why* the obvious solution is not acceptable? – AustinWBryan Jul 30 '18 at 13:25

2 Answers2

1

As per MSDN,

A static constructor is called automatically to initialize the class before the first instance is created. Therefore you can't send it any parameters.

But you can create a method static to init your static values.

Check fiddle https://dotnetfiddle.net/4fnahi

public class Program
{
    public static void Main()
    {
        Bus.Init(0);
        Bus bus1 = new Bus(71);
        Console.WriteLine(Bus.FirstBusNumber); // it prints 71 as your expected
    }
}

public class Bus
{
    public static int FirstBusNumber;

    public static void Init(int firstBusNumber) => FirstBusNumber = firstBusNumber;

    public Bus(int routeNum)
    {
        if (FirstBusNumber < 1)
           FirstBusNumber = routeNum;
    }
}
AustinWBryan
  • 3,249
  • 3
  • 24
  • 42
Antoine V
  • 6,998
  • 2
  • 11
  • 34
  • I think you missunderstood my question. But your idea with a static init method is an acceptable solution. Thanks. – Syrlia Jul 30 '18 at 09:46
  • @Syrlia: but it's not a good solution for your original problem (inject a connection-object that is used by all instances). You want to avoid multi-threading issues, believe me. A singleton is a better approach – Tim Schmelter Jul 30 '18 at 10:10
  • @TimSchmelter then what we can do? I run out of idea :( – Antoine V Jul 30 '18 at 10:11
  • @ThierryV: posting your real code in a new question would help. – Tim Schmelter Jul 30 '18 at 10:15
0

Firstly your example is from Microsoft docs, you can read more [here]

You, can't create a static constructor in c#. If you want specific type behavior you opt to instance class. There is a workaround, you can create a static method that settings static members, but you will need remember to use it explicitly. Static relate to type itself. Ensure that your static constructor set static globalStartTime for this type once, it initializes the class before the first instance is created You should really rethink if you need a static construct with a parameter.

proximab
  • 1,865
  • 1
  • 13
  • 18
  • We discuss the need of a static constructor with parameter below my question. Your answer doesn't solve my question. – Syrlia Jul 30 '18 at 09:44
  • I understand that, but you notice that even the Microsoft engineer did not come up with that. – proximab Jul 30 '18 at 09:47