C# - Downside to Setting Initial Value in Declaration
Is there any downside to a class like:
class Example1
{
protected string UserId = (string)Session["user"];
}
//versus
class Example2
{
protected string UserId;
public Example2()
{
UserId = (string)Session["user"];
}
}
If I always want to set this value is there any downside to Example1?
UPDATE:
Session["user"] is开发者_如何学运维 set in the Global.asax Session_Start. So if this fails. Nothing should work anyways.Your biggest problem is if this protected string UserId = (string)Session["user"];
fails. You have no recourse to degrade gracefully. By putting it in the constructor etc. You can check the Session and make a decision on what to do.
As a general rule, I only try and put values that I know are going to succeed like UserId = -1;
etc. and then modify them in a code block when I need to. You never know when something is going to go wrong and you need to recover from it.
The main downside is that you can only set the value using a single statement. If, for example, you wanted to check the Session key existed and if it didn't, you wanted to assign it a value, then you couldn't do it by setting the initial value.
If you check in the debugger, the setting of the value in the declaration (Example 1) happens before the constructor is called, so you need to make sure that it doesn't rely on anything set up from the constructor.
I'd strongly recommend using a "safe" cast.
UserId = Session["user"] as string;
This way, if the session item doesn't exist, or isn't a string, you don't fail. You simply get a null, which you can test for before using UserId.
AFAIK, there is no real difference between inline value initializers and constructor initialization, except in the order of execution of the statements, and the fact that you are very much restricted to single-line statements in the inline code.
The order of execution is that the value initializers are executed before any constructor logic, in a non-specific order, so if any of the initialization statements happen to have side-effects, you might be in for some nasty surprises. However, it is guaranteed that that code will run, so there is not a possibility of adding an additional constructor later, and forgetting to initialize some field.
I prefer using (chained) constructors to inline initialization, because I find the code to be more readable that way, and also i can do any additional checks that might become necessary down the road.
The guideline that I use: Use field initializers for basic / values known at compile time. If you're doing something like looking up a global collection or some non-trivial logic, move it into the ctor (for error handling/recovery as others have pointed out).
Assuming that you're sure that there would be no errors, the
- upside: field initializers are easy to read.
- downside: if you have a bunch of field initializers and multiple ctors, the IL for the initializers would be inserted at the top of each ctor leading to some IL bloat. So in this case, calling an Initialize like method would be better.
Other than that I don't see any downside to field initializers.
It's hard to know to how to begin to say that's not a good idea for many reason. First Session must be a global variable, otherwise your code won't even compile. I am guessing Session in your context here is the System.Web.HttpContext.Current.Session, so, your code won't even compile. Assume you have Session as a global variable, then you must properly initialize it and assign Session["user"], so how are you going to do it? Then you create this dependency between your class and the session, so how do you unit test? Plus all other reasons from all other answers.
You might someday want a second constructor with a different value of UserId.
AFAIK the constructor is always called after all fields are initialized. So in Example 2, you're first initializing the field to Null
and then to (string)Session["user"]
.
精彩评论