I'm way, way, way too tired, and can't figure out why this part of my code keeps throwing the following exception at Line 21:
System.NullReferenceException HResult=0x80004003 Message=Object reference not set to an instance of an object. Source=TANZ_Database
Any assistance would be great. I'll check back in after I get some sleep.
]]>I may be wrong, but I think C# is like Java in this respect. You can declare an array of objects, but you actually have to loop over those objects and create them.
public static Field[] fields = new Field[13]; for (int i = 0 ; i < 13 ; ++i) { fields[i] = new Field(...); }
]]>
yes an array in c# is just an array of pointers for reference types
]]>This is where C really shines. Array initialization is one of the best things about C.
struct ABC { const char* a; int b; float c; }; ABC array[2] = { {"Hello" , 1 , 0.5f} , {"World" , 2 , 1.5f} };
That is one of the features of C I use the most.
]]>You can do that in D.
]]>Thanks guys, that was it.
]]>It is possible to initialize arrays and things in C#
public static Field[] fields = new Field[] { new Field {Name = "Membership Types", Type = Types.List, Values = new List<string> { "Unpaid", "Paid", "Lifetime" } }, new Field {Name="First Name[s]", Type=Types.String}, new Field {Name="Surname", Type=Types.String}, new Field {Name="Post Code", Type=Types.String}, new Field {Name="Date of Birth", Type=Types.Date}, };
Possibly if you wrote a constructor for Field it might be made less unwieldy.
]]>Since you were all so helpful, here's another little problem I've run into. I have another function as follows:
It generates an exception at line 10, stating that f.Name is null. However, if I comment that line out and uncomment line 11, the program runs fine.
Any takers on this one?
edit:
Changing the DataField class definition to Peter's way of initiating the class fixed this problem. It's a shame you can't update threads to add extra credits.
]]>It's a shame you can't update threads to add extra credits.
I'll take a Lifetime membership to whatever club you're writing code for
]]>I'll take a Lifetime membership to whatever club you're writing code for
It's a non-profit organization that helps people with mental health issues.
They're actually pretty cool. I could have produced what they need in a day just using Access, but I said I'd write it for free using C#/.net as a learning exercise if they didn't mind it taking a but longer, and they replied that they're in no hurry and that they'd still pay me anyway.
It'll definitely be better than what they're using now, which is a multi-page Excel spreadsheet. I'm still storing the data in an Access database, so that if they want extra features at a later date and I'm not available, all their data is in a well known format.
]]>The second problem you reported: I assume the exception is being thrown from inside the Add function, with a check along the lines of
if (value == null) throw new NullReferenceException("value");
Meanwhile, MessageBox.Show probably just says
if (value == null) value = "";
With regard to the first problem, you may be able to simplify things by declaring your data type as a 'struct' instead of a 'class'. This means it will be passed around as a value instead of a reference, which comes with all its own subtleties, most notably this one:
var value = myArray[i]; value.x++; //modify some field of the struct myArray[i] = value; //this is necessary because 'value' was a copy
But the advantage is, when you make an array of them, they exist already. Think of it this way: a struct when converted to C will never have * or &, but a class will always have it.
]]>The second problem you reported: I assume the exception is being thrown from inside the Add function
That wouldn't explain why the watchlist was reporting that f.name had a value of null though, would it? The traceback also didn't include the .add function.
That bit about structs is useful info. Thanks.
]]>That wouldn't explain why the watchlist was reporting that f.name had a value of null though, would it?
Actually yes, that's exactly what I would expect. You're allowed to use f.name because f is not null. You're also allowed to pass null to a function.
The traceback also didn't include the .add function.
Perhaps it's a release build, or perhaps there's something about system libraries being omitted which I'm not entirely familiar with...?
]]>Actually yes, that's exactly what I would expect. You're allowed to use f.name because f is not null.
What I meant was that when I used the message box, it didn't display null, it displayed the name correctly, which is shouldn't? if it was set to null.
It's all working now though, which is the important part.
]]>I may be wrong, but I think C# is like Java in this respect. You can declare an array of objects, but you actually have to loop over those objects and create them.
public static Field[] fields = new Field[13]; for (int i = 0 ; i < 13 ; ++i) { fields[i] = new Field(...); }
Just a note, this is only true if Field is a "reference type" (i.e., an instance of a class). As Bruce alluded to, a "value type" (primitives, structs) work differently. Reference types are implicitly passed by reference (i.e., similar to pointers). Value types are implicitly passed by value (copied). If you create an array of integers in C# you do not have to allocate memory for each element of the array. Similarly, if you create an array of structs you don't need to allocate memory for each of them. They will be implicitly allocated. A value type variable cannot be null. Only reference types can be null because the value null means a "null reference". When you allocate an array of reference types you are allocating the memory for the reference itself, and that is initialized to null (sort of like allocating memory for a pointer versus the data that it points to). You need to allocate the objects themselves because there's no guarantee you ever wanted an object (depending on the program, having nulls in the array may be normal and expected).
]]>Reference types are implicitly passed by reference (i.e., similar to pointers). Value types are implicitly passed by value (copied). If you create an array of integers in C# you do not have to allocate memory for each element of the array. Similarly, if you create an array of structs you don't need to allocate memory for each of them. They will be implicitly allocated. A value type variable cannot be null. Only reference types can be null because the value null means a "null reference". When you allocate an array of reference types you are allocating the memory for the reference itself, and that is initialized to null (sort of like allocating memory for a pointer versus the data that it points to). You need to allocate the objects themselves because there's no guarantee you ever wanted an object (depending on the program, having nulls in the array may be normal and expected).
That's a nice explanation. It's been 25 years now since I studied Computer Science. I'm a little rusty around the edges.
edit:
Upon reading up on structs, it appears that part of what you said isn't correct. A struct is a value type, but it can be null -
A struct can be used as a nullable type and can be assigned a null value.
]]>
Upon reading up on structs, it appears that part of what you said isn't correct. A struct is a value type, but it can be null -
A struct can be used as a nullable type and can be assigned a null value.
That's a very misleading statement.
I'm in Linux right now so I'm using Mono to compile, but Microsoft's compilers should also yield an error:
mono-csc Nullable.cs Nullable.cs(9,23): error CS0037: Cannot convert null to `Application.Foo' because it is a value type Compilation failed: 1 error(s), 0 warnings
What that statement might mean is that you can wrap structs (and other value types) up into a `Nullable<T>` class instance to make them nullable. This type is built right into the compiler. X? is the same as `Nullable<X>`.
Note, we get warnings because we didn't actually use the variables, but the program compiled successfully.
Nullable2.cs(9,18): warning CS0219: The variable `foo1' is assigned but its value is never used Nullable2.cs(10,27): warning CS0219: The variable `foo2' is assigned but its value is never used Nullable2.cs(13,17): warning CS0219: The variable `foo5' is assigned but its value is never used Compilation succeeded - 3 warning(s)
Note, accessing `Nullable<T>.Value` will throw if there is no value. You can test it with the HasValue property (but you can also compare the Nullable<T> to null).
Append:
Note that structs have limitations in C#. Unlike C++ where you can do all the same things, C# enforces stricter rules. This limits their usefulness. In the wild you won't encounter them often. Which is helpful since the semantics implicitly change.
]]>In the wild you won't encounter them often
Some often-used types in System are structs.. For example KeyValuePair<T>, and... Nullable<T> itself !
]]>The change of semantics between classes and structs can be mitigated. If you're designing a struct, then make all its fields 'readonly'. This will prevent you assigning them from anywhere except the constructors. Consequently, it will be impossible to try to update a struct without realising you are working on a copy - you can only update a value by making a new instance of the whole struct, like with java.lang.String (which has the opposite problem, being a class that wants to behave a bit like a struct).
]]>