I have a property like this:
public Tuple<String, String>[] Breadcrumbs { get; set; }
and I have a test in one of my methods like this:
if (Breadcrumbs != null && Breadcrumbs.Length > 0) { }
Depending on when this method is called, Breadcrumbs may not have been set. In one test, Breadcrumbs == null evaulates to true.
Will unset properties always have a value? (Will it always be null?)
An automatically-implemented property which hasn't been explicitly set by any code will always have the default value for the property type - which is null for reference types. (For int it would be 0, for char it would be '\0' etc).
An automatically implemented property like this is just equivalent to:
private PropertyType property;
public PropertyType Property
{
get { return property; }
set { property = value; }
}
... except that the backing variable has an unspeakable name (you can't refer to it in code) so it will always start off with the default value for the type.
Auto-properties use backing fields and are compiled to regular properties.
If the Property-Type is a reference type the value would be null, if not the value would be the default value.
Class member variables (called fields), and thus backing variables of properties, are always initialized to their default value, if they are not initialized explicitly, which is null for reference types. The default value for all types is the value whose binary representation consists of all bits set to 0.
On the other hand, C# requires you to initialize local variables explicitly. These are: variables declared in methods, constructors and property accessors and out method parameters; i.e. they are treated as undefined until you assign them a value.
It's logically impossible for it not to have a value. It's going to have to return something, some bunch of 1s and 0s that is at least believed to be a reference to a Tuple<String, String>[], so to that extent it has a value.
It's also the case that all fields in classes get set to their default value (default(T) for whatever type T they are, which is null for all reference types). Otherwise it would be possible to have an object that was in a state that not only didn't make any sense in terms of what it does, but which didn't make any sense by the rules of what .NET expects objects to do. This includes the hidden fields behind automatic properties.
Now, in some languages we can do the equivalent of this:
public Tuple<String, String>[] Breadcrumbs
{
get
{
Tuple<String, String>[] whatIWillSend;
return whatIWillSend;
}
}
If this were allowed, whatIWillSend would have a value defined not by any concious decision on your part, but by what happened to be in memory at the time. It could be null, it could be a valid Tuple<String, String>[] by sheer coincidence (but not the one you wanted to use!), it could be a Dictionary<int, List<string>> that the runtime is now going to think is actually a Tuple<String, String>[] (there goes the type-safety of the entire system), it could be a quarter of a decimal structure. (In the languages that allow such things, it could also be a well-known value that debuggers for such languages set in these cases precisely so to help find bugs caused by it).
That's the closest thing we can get to a property not having a value. Note though that:
It would still have a value, just not a meaningful value.
We aren't allowed to do this in C# anyway.
Related
I have a sequence of structs like so:
struct Foo { }
...
// somewhere else
var foos = GetListOfFoos();
...
// somewhere else
var foo = foos.FirstOrDefault();
Now, should I just go ahead and use the foo I just retrieved without worrying about nullability, of course because structs are not nullable since they're value types.
It just feels a bit worrying.
I know this is a stupid question and the answer is, "Yes, just use it without any checks for null." But I don't know why I am asking this even or what the question here is.
I am not missing anything by not checking for nullability here, right? There cannot be an invalid state for structs put inside that IEnumerable<T>, right?
Of course, I understand that if Foo had uninitialized members because it declared a parameterized ctor that did not initialize each and every member, one or more members of the instance of Foo will be in an unsable state. But as such each instance of Foo in that list will amount to something and there's no need to check for nulls or anything as there is no such thing as default(Foo), right? Of course, just confirming.
Even if value types are not null you should worry about this value being the default value if that was exceptional or not expected.
there is no such thing as default(Foo)
Sure, It will return an instance of this type where all members are nitialized to their default alues.
If you take f.e. struct Guid then default(Guid) returns an instance which is equal to Guid.Empty or new Guid().
So my advice is, don't compare with default(yourStruct) because that could lead to nasty bugs if the default struct could be a valid instance. Instead you could use Any:
bool containsAny = foos.Any();
if(containsAny)
{
Foo firstFoo = foos.First();
}
MSDN: default
returns null for reference types(class types and interface types)
zero for numeric value types
for user-defined structs, it returns the struct initialized to the zero bit pattern, which produces 0 or null for each member depending on whether that member is a value or reference type. For nullable value types, default returns a System.Nullable<T>, which is initialized like any struct.
If T is a struct, you can't check for null: it will never be null, and a real "zero" (equivalent) in the list/sequence will be indistinguishable from "no there weren't any values in the list/sequence".
No, you don't need to check for null here.
In WinRT, settings are stored as objects which means that you end up doing a lot of casting to get back to the type you want. Since that seems to map onto one of the reasons why generics were added to C#, I've been trying to simplify my code so that I can do something like:
public string LastRunVersion
{
get
{
return GetLocalSettingsValue<String>("LastRunVersion", null);
}
set
{
SetLocalSettingsValue("LastRunVersion", value);
}
}
The problem I'm having is with the signature for SetLocalSettingsValue. I tried:
private T GetLocalSettingsValue<T>(string tag, T defaultValue) where T:Object
but Object isn't allowed because it isn't a valid constraint. I know that I only store booleans and strings, so I then tried:
private T GetLocalSettingsValue<T>(string tag, T defaultValue) where T:String, bool
but the compiler says that "A type used as a constraint must be an interface, a non-sealed class or a type parameter".
What do I need to do with the definition in order to allow me to use string and bool?
Thanks.
Implementing two different methods, as Sriram suggests, does seem like the simplest solution for the immediate concern. That said, your generic approach is viable, has precedent, and will make it much easier to extend the code in the future.
In fact, what you tried was nearly correct. The main thing is that you don't actually need a constraint at all. The method declaration is fine without it, and though you don't show the method body, as long as all you need to do is cast some object reference to the type T, that will work:
private T GetLocalSettingsValue<T>(string tag, T defaultValue)
{
object value;
// initialize/retrieve the value somehow
// Check for value present, return default if missing, cast otherwise
return value != null ? (T)value : defaultValue;
}
In fact, since you are passing a default value, type inference will allow you to omit the type parameter in some cases. For example:
public string LastRunVersion
{
get { return GetLocalSettingsValue("LastRunVersion", (string)null); }
}
If you had a non-null default value, the above would be more interesting. :) With the null value, you have to cast it to string just for the compiler to know what the correct type is, which is practically the same as just providing the type parameter. But if you were passing a string literal or the value of a string variable, the type would be clear and the name of the type would not need to be provided at all (not even as a cast).
More interesting is the bool scenario:
public string LastRunVersion
{
get { return GetLocalSettingsValue("SomeBooleanSetting", false); }
}
Here, the literal has a clear type, and so you don't need to provide the type name in any form.
Finally, note that C# does have the idea of default values for types. If you want to support non-null, non-zero default values, then your current approach is good. However, if your defaults are always going to be things like null, false, or 0 (e.g. for an int, should you ever need to store something like that), then you don't need the default parameter at all:
private T GetLocalSettingsValue<T>(string tag)
{
object value;
// initialize/retrieve the value somehow
// Check for value present, return default if missing, cast otherwise
return value != null ? (T)value : default(T);
}
Any reference type will use null as the default. For value types, you will get whatever the value would be if you created an instance using the parameterless constructor (all value types have a parameterless constructor). Numeric types all default to their version of 0, bool defaults to false, etc.
Naturally, in that case you will always have to provide the type parameter, since there aren't any arguments from which the type parameter could be inferred.
If you use an initializer list to create a struct, do the members you leave out get a known default value?
public struct Testing
{
public int i;
public double d;
public string s;
}
Testing test = new Testing { s="hello" };
I found a link at Microsoft that implies it but does not state so explicitly: Default Values Table (C# Reference).
A small test program shows that it does not generate a compiler error and produces the expected results. I know better than to rely on simple tests for guarantees though. http://ideone.com/nqFBIZ
Yes, they contain default(T) where T is the type of the value.
Object references will be null.
Excerpt:
As described in Section 5.2, several kinds of variables are
automatically initialized to their default value when they are
created. For variables of class types and other reference types, this
default value is null. However, since structs are value types that
cannot be null, the default value of a struct is the value produced by
setting all value type fields to their default value and all reference
type fields to null.
Taken from here:
http://msdn.microsoft.com/en-us/library/aa664475(v=vs.71).aspx
I remember when studying the MOC for the certification that they explicitly state this. It is a guaranteed feature of the language.
To expand on pid's answer:
test = new Testing { s = hello }
is specified as having the semantics of:
Testing temp = new Testing();
temp.s = "hello";
test = temp;
The default constructor of a value type is documented as the constructor which sets all the fields of the instance to their default values.
More generally, the C# language requires that any constructor of a value type have the property that all fields be definitely assigned before the constructor terminates normally.
Now, if no constructor is called then there are two cases. If the variable is initially assigned then the variable acts the same as though the default constructor was called. For example, if you say
Testing[] test = new Testing[1];
Then test[0] is initialized to the default value the same as if you'd said
Testing[] test = new Testing[1] { new Testing() };
If the variable is not initially assigned, for example, a local variable, then you are required to definitely assign all the fields before you read them. That is, if we have a local:
Testing test;
test.s = "hello";
Console.WriteLine(test.d); // ERROR, test.d has not been written yet.
Note also that mutable structs are a worst practice in C#. Instead, make a public constructor that sets all the fields, make the fields private, and put property getters on top of them.
I'd like to take simple public properties and turn them into anonymous accessors, but some of my logic requires the initial values of the accessors/properties be null, can I rely on anonymous accessors to be null if I've not assign them a value?
currently :
public string XML = null; // set XML or XMLPath to turn on XML stuff
public string XMLPath = null;
compared to :
public string XML {get; set;}
public string XMLPath {get; set;}
You don't need to do anything. They are null by default. This is true also for fields. Actually, a automatic property also uses a field and that's why the default value of an automatic property is null (or default(T) to be more precise).
Unassigned auto-implemented properties are defined to start with the default value for their type. So reference types start null.
New class fields are always initialized with nulls (except simple types which are initialized with them default values, like 0 for integer). You do not need to assign the null to them. It all aplies to auto implemented properties and fields in anonymouse object too.
Only method variables are not initialized, but as for them if you'll try to read them without initializing them first you'll get the compiler error first, so you don't need to worry here either.
Conclusion: C# always cares about not accessing uninitialized variables on compile-time, there is no chance that you will access variable that do not have default value assigned on runtime.
I have a class containing a number of properties, something like:
public class Update
{
public int Quantity { get; set; }
public decimal Price { get; set; }
public string Name { get; set; }
}
Each instance of Update does not necessarily have each property set, and another part of the system needs to know which have been set, and which haven't.
One option I've got is to make all the value types Nullable and so a null value would represent the concept of not being set. Whilst this would work, I don't really like the idea of having some properties explicitly Nullable (the value types) and some nullable by virtue of being a reference type. The class definition would look ugly and I'm not convinced a null check is semantically the best approach.
I could create a class very similar to Nullable<T> that has no constraint on the T with an IsSet property. I prefer this option to using Nullable, but I'd still like to see if anyone has an alternative representation that's better than the options I've suggested.
You really should stick to the preexisting idiom here. Use the built-in nullability.
I see your concern with nullability being different for value and ref types. Your workaround would work. But it is just a cosmetic change which gains you litte. I recommend that you change yourself instead of changing the code in this case. Try to fit yourself to the existing conventions.
Edit: Sometimes you need to be able to make a value optional in generic code. In this case you need to use some custom option type. By from experience I can tell that this is pretty nasty to use. It is not my solution of choice.
The reference types are already nullable, effectively - if you use int?, decimal? and string then every one of your properties can be null.
The problem comes if you ever want to set the string value to a null reference - if null is effectively a valid value which is set.
You certainly could write a Maybe<T> type, but I'm not sure I would - I would probably just use null... aside from anything else, it'll be more familiar for others reading the code who are used to C# idioms. For all the "anti-null" sentiment around (which I do share in many situations) there are cases where it's the simplest approach.
I don't really like the idea of having some properties Nullable (the
value types) and some not (the reference types)
Reference types are obviously nullable.
string t = null; //is totally valid
I'd say that Nullable is exactly what you want to use for this purpose.
You could wrap the members with properties (as you already do) to have the class show normal values to the outside alongside with "is it set"-methods to check if needed. But on the inside I'd use Nullable.
To suggest you something new... If you just talking about one class like Update with a limited number of members I would use just IsSet.
But if you have i.e. a number of similar classes with this behavior or a lot of properties I could suggest you using t4 templates. You can, in example, get class properties (of needed type or attribute) as it described in this article and auto generate code based on the list of properties (implementing any design you want automatically)
I could describe it more if one is interested...
The solution here to
use nullable wherever null is not a valid option
use a default value wherever null is a valid option but you are perfectly sure that a given value won't occur
use a boolean flag for each property where null is a valid value and you can't name a default which won't be used ever.
Examples:
Quantity should be nullable, because if it is set its value won't be null ever
Name should be defaulted to "" if Name might be null (the lack of a name) and you are sure Name will never be ""
A flag, let's say nameSet should be used if Name might have a null value and you can't think of a default value. This flag would be false by default and when you first set the value of Name, the flag should be set to true too.
If you want to handle all your properties in the same way a solution would be to create a class which would contain an Object and a boolean flag. The Object would store the value of the property and the flag would store whether the property was initialized, but I don't like this, because it creates a boolean flag even if it's not needed.