mati
mati

Reputation: 5348

When are inline static variables initialized in a class?

Suppose we have a class like:

Public Class Question 

    Private Shared _field as Integer = CrazyIntegersRepository.GetOne()

    ' Some other useful things go here

End Class

And the method GetOne throws an exception... How can we manage that? Is a good practice to rewrite that into a static constructor?
When is the GetOne method going to be executed if we leave it there in the inline _field declaration?

Upvotes: 1

Views: 291

Answers (3)

Alex Essilfie
Alex Essilfie

Reputation: 12613

If you go by p.campbell's suggestion, you'll have to declare at least one instance of the class in order to have the _field variable initialised. I assume, from the Shared keyword in the declaration of the variable, that you want it to be accessible from all instances of the class whether or not they have been specifically initialised.

In order to achieve that functionality, you'll have to modify your class as follows:

Public Class Question 

    Private Shared _field as Integer

    Shared Sub New()
        _field = CrazyIntergersRepository.GetOne()
    End Sub
    ' Some other useful things go here

End Class


Using this method, the _field variable will be initialised the first time the class is used because the default constructor is declared as Shared. You could optionally wrap the method in a Try...Catch block in order to trap exceptions that might occur.

Upvotes: 0

p.campbell
p.campbell

Reputation: 100587

Regarding your question around managing the possible exceptions, go with your gut on that one. Any code that can create an exception should be put into a method. In this case, the constructor would be the best place. So perhaps something like:

Public Sub New()
    Try
        _field as Integer = CrazyIntegersRepository.GetOne()
    Catch ex As Exception
        'log it / deal with it as you will
    End Try
End Sub

Upvotes: 0

Jon Skeet
Jon Skeet

Reputation: 1501123

Note: I'm assuming VB works the same as C# here. I'd be surprised if they differed on this.

If you leave it there (and don't have a static constructor), it will depend on the version of .NET you're using. It's only guaranteed to be run "at some point before the first reference to a static field". You can even create instances and the type initializer may not run! If you have a static constructor (even an empty one), the type initializer will be run directly before the first reference to any constructor or any static member. (Basically, almost anything you actually do with it will initialize it.)

The actual observed behaviour has become lazier in .NET 4 compared with .NET 3.5, as I blogged about. Note that this is only talking about the desktop framework; I don't know what Silverlight or the Compact Framework do.

If the method can throw an exception, I'd be tempted to do it rather more lazily in the first place, in a method call, maybe caching the result appropriately. That way, the method can let the exception bubble up and the caller can try again later. That's appropriate if it's a potentially transient exception you're considering. If it's something which indicates the whole system is unusable, it's fine to let the type initializer fail.

Upvotes: 4

Related Questions