I have the following code ( extracted from the real code )
public static class AssemblyLogger {
public static Lazy<Window> Window { get; } = new Lazy<Window>(NewWindowHandler);
public static IScheduler Scheduler =>
new DispatcherScheduler( Window.Value.Dispatcher );
}
When I call Scheduler I get a NullReferenceException. Stopping with the debugger I see
As far as I know this should be impossible. Window is statically initialized and read only and so any further access to it should be get only and it should never be null.
I have set a breakpoint against the initializer but it never gets hit
I have also tried a static readonly field and still the same problem
public static readonly Lazy<Window> Window = new Lazy<Window>(NewWindowHandler);
Is it possible to have a race condition against the static initialization?
Attempts to make an MCVE so far are not successful. The below spec tests my minimal postable code and the real code. The MCVE one passes :( and the real one fails. I am missing some context and need further work to isolate the issue.
public class Tester
{
public static class AssemblyLoggerMCVE
{
public static Lazy<Window> Window { get; } = new Lazy<Window>(NewWindowHandler);
private static Window NewWindowHandler() => new Window();
public static IScheduler Scheduler =>
new DispatcherScheduler(Window.Value.Dispatcher);
}
/// This passes
[StaFact]
public void AssemblyLoggerMCVEShouldWork()
{
AssemblyLoggerMCVE.Scheduler.Should().NotBeNull();
}
/// This fails
[StaFact]
public void AssemblyLoggerShouldWork()
{
AssemblyLogger.Scheduler.Should().NotBeNull();
}
}
The error can be clearly replicated by the following test case which has more context than the question suggested was necessary.
public class Tester
{
public class AssemblyLoggerControlModel
{
public static IScheduler S = AssemblyLoggerMCVE.Scheduler;
}
public class AssemblyLogger
{
public static AssemblyLoggerControlModel ModelInstance { get; } =
new AssemblyLoggerControlModel();
public static readonly Lazy<Window> Window =
new Lazy<Window>(NewWindowHandler);
private static Window NewWindowHandler() => new Window();
public static IScheduler Scheduler =>
new DispatcherScheduler(Window.Value.Dispatcher);
}
}
There is a circular dependency between static initializers. Static initialization of static property AssemblyLogger.ModelInstance causes static property AssemblyLoggerControlModel.S to be intitialized which then tries to call the static AssemblyLogger.Scheduler method which in turn tries to access Window which because the static initialization for AssemblyLogger is not complete is still null.
Basically my code is pure evil and the best thing to do is
Related
I have a static class with a static constructor. I need to pass a parameter somehow to this static class but I'm not sure how the best way is.
What would you recommend?
public static class MyClass {
static MyClass() {
DoStuff("HardCodedParameter")
}
}
Don't use a static constructor, but a static initialization method:
public class A
{
private static string ParamA { get; set; }
public static void Init(string paramA)
{
ParamA = paramA;
}
}
In C#, static constructors are parameterless, and there're few approaches to overcome this limitation. One is what I've suggested you above.
As per MSDN, A static constructor is called automatically to initialize the class before the first instance is created. Therefore you can't send any parameters.
CLR must call a static constructor, how will it know which parameters to pass it?
So don't use a static constructor.
Here's the work around for your requirement.
public class StaticClass
{
private int bar;
private static StaticClass _foo;
private StaticClass() {}
static StaticClass Create(int initialBar)
{
_foo = new StaticClass();
_foo.bar = initialBar;
return _foo;
}
}
Static constructors have the following properties:
A static constructor does not take access modifiers or have parameters. A static constructor is called automatically to
initialize the class before the first instance is created or any
static members are referenced.
A static constructor cannot be called directly.
The user has no control on when the static constructor is executed in the program.
A typical use of static constructors is when the class is using a log file and the constructor is used to write entries to this file.
Static constructors are also useful when creating wrapper classes for unmanaged code, when the constructor can call the LoadLibrary
method.
If a static constructor throws an exception, the runtime will not invoke it a second time, and the type will remain uninitialized for
the lifetime of the application domain in which your program is
running.
If by "HardCodedParameter" you really mean hard coded, you can use constants.
public static class YoursClass
{
public const string AnotherHardCodedParam = "Foo";
}
public static class MyClass
{
private const string HardCodedParam = "FooBar";
static MyClass()
{
DoStuff(MyClass.HardCodedParam);
DoStuff(YoursClass.AnotherHardCodedParam);
}
}
Also, you can use static readonly properties.
Constructors on non-static class have have the benefit to ensure they're properly initialized before they're actually being used.
Since static classes don't have this benefit, you have to make ensure that yourself.
Use a static constructor with an obvious name, then in the relevant portion of your static procedures check to make sure the initialization has been performed.
The example below assumes your want to "initialize" your static class with a Form object.
public static class MyClass
{
private static Form FormMain { get; set; }
public static void Init(Form initForm)
{
FormMain = initForm;
}
private static bool InitCheck()
{
return FormMain != null ? true: false;
}
public static void DoStuff()
{
if (InitCheck())
{
// Do your things
}
else
{
throw new Exception("Object reference not set to an instance of an object");
}
}
}
I have this code:
static class Global
{
public static readonly IChannelsData Channels = new ChannelsData();
public static readonly IMessagesData Messages = new MessagesData();
}
My understanding is that, because this class is static, it is impossible for Global.Channels or Global.Messages to be null now that they have been given an instance.
However, I try to access the property with
public class Channel : IComparable
{
...
private SortedList<string, Message> _messages;
[JsonConstructor]
public Channel()
{
_messages = new SortedList<string, Message>();
}
[OnDeserialized]
private void Init(StreamingContext context)
{
**Global.Channels.RegisterChannel(this);**
}
...
}
I get a NullReferenceException on Global.Channels, which I have confirmed in the immediate window. Further confusing me, I can hit the breakpoint at new ChannelData(), so I know the static member is being populated - successfully - at some point.
More context, comment request:
private Hashtable _channels;
public ChannelsData()
{
_channels = new Hashtable();
foreach(Channel channel in SlackApi.ChannelList())
{
_channels.Add(channel.GetHashCode(), channel);
}
}
It feels like something similar to the problem here. However, in my situation I'm deserializing using JSON.NET and not WCF and the property in question is in a separate static class, not in the same class. I also can't use the workaround of a solution posted there.
Full stack trace:
at Vert.Slack.Channel.Init(StreamingContext context) in C:\\Vert\Slack\Channel.cs:line 48
And error:
Object reference not set to an instance of an object.
I've been able to reproduce it with the following:
class Program
{
static void Main(string[] args)
{
var m = Global.Messages;
}
}
[Serializable]
public class Blah
{
[OnDeserialized]
public void DoSomething(StreamingContext context)
{
Global.Channels.DoIt(this);
}
}
static class Global
{
private static Blah _b = Deserialize();
public static readonly IChannelsData Channels = new ChannelsData();
public static readonly IMessagesData Messages = new MessagesData();
public static Blah Deserialize()
{
var b = new Blah();
b.DoSomething(default(StreamingContext));
return b;
}
}
Essentially, the order of execution is:
var m = Global.Messages; causes the static initializer to run for Global.
According to ECMA-334 regarding static field initialization:
The static field variable initializers of a class declaration
correspond to a sequence of assignments that are executed in the
textual order in which they appear in the class declaration. If a
static constructor (§17.11) exists in the class, execution of the
static field initializers occurs immediately prior to executing that
static constructor. Otherwise, the static field initializers are
executed at an implementation-dependent time prior to the first use of
a static field of that class
This is the root cause. See the comments for more context on the circular reference
This essentially means that we're calling Deserialize and hitting Global.Channels.DoIt(this); before the initializer has a chance to finish setting up. As far as I'm aware, this is the only way a static field cannot be initialized before being used - after some testing, they are indeed created even when using run-time dispatches (dynamic), reflection and GetUninitializedObject (for the latter, initialization is done on the first method call, however)..
Though your code may be less obvious to diagnose (for example, if the chain is kicked off by another static class referencing). For example, this will cause the same issue but is not as immediately clear:
class Program
{
static void Main(string[] args)
{
var t = Global.Channels;
}
}
[Serializable]
public class Blah
{
[OnDeserialized]
public void DoSomething(StreamingContext context)
{
Global.Channels.DoIt();
}
}
public interface IChannelsData { void DoIt(); }
class ChannelsData : IChannelsData
{
public static Blah _b = Deserialize();
public static Blah Deserialize()
{
var b = new Blah();
b.DoSomething(default(StreamingContext));
return b;
}
public void DoIt()
{
Console.WriteLine("Done it");
}
}
static class Global
{
public static readonly IChannelsData Channels = new ChannelsData();
public static readonly IMessagesData Messages = new MessagesData();
}
So:
If you have anything else in Globals before those fields, you should investigate them (if they were left out for brevity). It may be simple as moving the Channels declaration to the top of the class.
Inspect ChannelsData for any static references, and follow those to the source.
Setting a breakpoint in DoSomething should give you a stack trace back to the static initializers. If it doesn't, try to replicate the issue by invoking new Blah(default(StreamingContext)) where it would usually be deserialised.
My code is as follows
class MyStaticClass
{
static MyStaticClass{};
public static readonly MyStaticClass Instance = CreateMe();
public static int GetSomeValue = GetValue();
private static int GetValue()
{
return 0;
}
private static MyStaticClass CreateMe()
{
Console.WriteLine("This method was called");
return new MyStaticClass();
}
}
public class Program
{
public static void Main()
{
int val=MyStaticClass.GetSomeValue;
}
}
O/p:
This method was called
When I call val why does the debugger accesses CreateMe method ? Is it that any static method I access it will access all the static methods in the class ?
The method CreateMe() is called because you are calling in when you create object Instance in the following statement.
public static readonly MyStaticClass Instance = CreateMe();
This is static object in your class and is created as you access the class which you did by MyStaticClass.GetSomeValue.
Dubugging the code will give you clear view of the order of the statements get executed. You can go through this detailed article on MSDN regarding debugging Debugger Roadmap
You have a static initializer for a static field. As part of program startup, all static fields are evaluated.
Edit: small clarification here:
The static fields in a particular class are evaluated in declaration order, but there in no particular order for which class has it's static fields initialized first.
Now, if you had a static property, that would be different.
MSDN link
Both fields have been initialized using the static methods. So, in that case, all the static methods will be evaluated.
In my Application a have a set of Data Providers and Redis Cache.
Each execution different providers are used, but they all store own Data in Redis:
hset ProviderOne Data "..."
hset ProviderTwo Data "..."
I would like have one method That will delete Data for all providers that are present in code.
del ProviderOne
del ProviderTwo
I have made next code:
void Main()
{
// Both providers have static field Hash with default value.
// I expected that static fields should be initialized when application starts,
// then initialization will call CacheRepository.Register<T>() method
// and all classes will register them self in CacheRepository.RegisteredHashes.
// But code start working only when i created this classes (at least once)
// new ProviderOne();
// new ProviderTwo();
CacheRepository.Reset();
}
public abstract class AbstractProvider
{
//...
}
public class ProviderOne : AbstractProvider
{
public static readonly string Hash =
CacheRepository.Register<ProviderOne>();
//...
}
public class ProviderTwo : AbstractProvider
{
public static readonly string Hash =
CacheRepository.Register<ProviderTwo>();
//...
}
public class CacheRepository
{
protected static Lazy<CacheRepository> LazyInstance = new Lazy<CacheRepository>();
public static CacheRepository Instance
{
get { return LazyInstance.Value; }
}
public ConcurrentBag<string> RegisteredHashes = new ConcurrentBag<string>();
public static string Register<T>()
{
string hash = typeof(T).Name;
if (!Instance.RegisteredHashes.Contains(hash))
{
Instance.RegisteredHashes.Add(hash);
}
return hash;
}
public static void Reset()
{
foreach (string registeredHash in Instance.RegisteredHashes)
{
Instance.Reset(registeredHash);
}
}
protected void Reset(string hash);
}
interface IData{}
interface IDataProvider
{
string GetRedisHash();
IData GetData();
}
intefrace IRedisRepository
{
}
How make it working?
You can just access any static method/property of your class - i.e. Provider1.Name:
public class Program
{
static void Main(string[] args)
{
Console.WriteLine(Provider1.Name + Provider2.Name);
Console.ReadLine();
}
}
In C# static constructor (one that initializes all static fields) is called only if any method of type is used as covered in C# specification 10.11 Static constructors:
The static constructor for a class executes at most once in a given application domain. The execution of a static constructor is triggered by the first of the following events to occur within an application domain:
•An instance of the class is created.
•Any of the static members of the class are referenced.
Note that magical registration is very hard to write unit tests for - so while your approach would work it may be better to use some known system that allow registering objects that is convenient to test.
i am a little confused by multi-thread access risk on a static property in C#.
public class MyClass
{
public static MyClass Static
{
get
{
var c = new MyClass();
c.SomeProperty = "12345";
c.OtherProperty = DateTime.Now.ToString();
return c;
}
}
}
This example class provides a static property that create a new instance of MyClass,
like a method:
public class MyClass
{
public static MyClass Static()
{
var c = new MyClass();
c.SomeProperty = "12345";
c.OtherProperty = DateTime.Now.ToString();
return c;
}
}
Obviously, this property is not a "storage" box for an instance of MyClass, but it behaves like a static method (that, if i reading good a msdn article, is completely thread-safe).
My question is: i risk something with using this concept ?
Especially in a web or multi-thread enviroinment ?
There is a no particular utility in using it, only for simple reading and cleaning code:
MyClass.Static.SomeProperty = "Something";
is more clear than
MyClass.Static().SomeProperty = "Something";
All help will be appreciated
Thanks
In both your examples you're returning a new instance of MyClass every time the property is accessed. There is no danger that you'll have any concurrency issues when multiple threads access the static property method at the same time, because they're actually modifying the properties of their own instance of MyClass and not sharing it between them.
If you had something like this instead:
public class MyClass
{
private static MyClass _myClass;
public static MyClass Static
{
get
{
return _myClass ?? (_myClass = new MyClass());
}
}
}
...then you'd cause problems when two threads attempted to write/read properties of the resulting MyClass instance, because they're operating on the same MyClass reference _myClass.
Even so, there are two issues with the code you've posted:
You need to change it to a method and rename it, because it's actually creating something, not accessing a static version of anything. Then you can operate on the return value. Something like this:
public class MyClass
{
public static MyClass Create()
{
var c = new MyClass();
c.SomeProperty = "12345";
c.OtherProperty = DateTime.Now.ToString();
return c;
}
}
Then use it like this:
var myClass = MyClass.Create();
myClass.SomeProperty = "Stuff";
The way you're setting properties currently means their values aren't persisted, because a new MyClass is created the next time the Static property is accessed.
If when you set SomeProperty you actually want a static instance to be updated you'll need to lock on a static object to solve the multi threading issue - something like this:
public static class MyClass
{
private static readonly object locker = new object();
private static string someProperty;
public void SetSomeProperty(string val)
{
lock (locker)
{
someProperty = val;
}
}
public void GetSomeProperty()
{
lock (locker)
{
return someProperty;
}
}
}
It seems that you are creating a static factory method that will give you a fully instantiated object.
Threading would not be an issue here because every time you call this method or property you are creating a new object. If 2 threads call the same method at the same time they will each keep on working on the object they are dealing with
Having said that - Perhaps you should reexamine how you are using the class - because if you call this in your code
MyClass.Static.SomeProperty = "Something";
You are basically throwing away the object after it has been instantiated
you would need to assign it to a variable and store it. - the next time you call that function you will receive a new object.
Perhaps I was not able to explain properly, my question was referred multithreaded access on static properties.
I can confirm that they are thread-safe, if the returned object is bound to the current thread.
Here is the example of what I implemented:
public interface IObjectFactory
{
T CreateOrReuse<T>() where T : class, new();
T CreateOrReuse<T>(string key) where T : class, new();
T CreateOrReuse<T>(string key, params object[] args) where T : class;
}
public class ThreadObjectFactory : IObjectFactory
{
// implementation to create and store into the Thread Data
}
public class HttpSessionObjectFactory : IObjectFactory
{
// implementation to create and store into the current session
}
Now the singleton:
public class MyClass
{
public int PageLoadCounter = 0;
public static MyClass Static
{
get
{
IObjectFactory factory = new HttpSessionObjectFactory();
return factory.CreateOrReuse<MyClass>();
}
}
}
And this is the final use:
public class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
MyClass.Static.PageLoadCounter++;
}
}
Thanks for the replies, even if the question was not very clear