|
Any C# coders? I need some help |
LennyLen
Member #5,313
December 2004
|
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
1using System;
2using System.Collections.Generic;
3
4namespace TANZ_Database
5{
6 enum Types {Int, String, List, Date};
7
8 class Field
9 {
10 public String Name;
11 public Types Type;
12 public List<string> Values;
13 }
14
15 class DataField
16 {
17 public static Field[] fields = new Field[13];
18
19 public void PopulateDataFields()
20 {
21 fields[0].Name = "Membership Types";
22 fields[0].Type = Types.List;
23 fields[0].Values.Add("Unpaid");
24 fields[0].Values.Add("Paid");
25 fields[0].Values.Add("Lifetime");
26
27 fields[1].Name = "First Name[s]";
28 fields[1].Type = Types.String;
29
30 fields[2].Name = "Surname";
31 fields[2].Type = Types.String;
32
33 fields[3].Name = "Address";
34 fields[3].Type = Types.String;
35
36 fields[4].Name = "Post Code";
37 fields[4].Type = Types.Int;
38
39 fields[5].Name = "Date of Birth";
40 fields[5].Type = Types.Date;
41
42 }
43 }
44}
Any assistance would be great. I'll check back in after I get some sleep.
|
Edgar Reynaldo
Major Reynaldo
May 2007
|
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(...); }
My Website! | EAGLE GUI Library Demos | My Deviant Art Gallery | Spiraloid Preview | A4 FontMaker | Skyline! (Missile Defense) Eagle and Allegro 5 binaries | Older Allegro 4 and 5 binaries | Allegro 5 compile guide |
jmasterx
Member #11,410
October 2009
|
yes an array in c# is just an array of pointers for reference types Agui GUI API -> https://github.com/jmasterx/Agui |
Edgar Reynaldo
Major Reynaldo
May 2007
|
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. My Website! | EAGLE GUI Library Demos | My Deviant Art Gallery | Spiraloid Preview | A4 FontMaker | Skyline! (Missile Defense) Eagle and Allegro 5 binaries | Older Allegro 4 and 5 binaries | Allegro 5 compile guide |
Chris Katko
Member #1,881
January 2002
|
You can do that in D. -----sig: |
LennyLen
Member #5,313
December 2004
|
Thanks guys, that was it.
|
Peter Hull
Member #1,136
March 2001
|
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.
|
LennyLen
Member #5,313
December 2004
|
Since you were all so helpful, here's another little problem I've run into. I have another function as follows: 1private void RadioSpecificFilter_CheckedChanged(object sender, EventArgs e)
2{
3 if (radioSpecificFilter.Checked == true)
4 {
5 radioNoFilter.Checked = false;
6 radioRangeFilter.Checked = false;
7
8 foreach (Field f in DataField.fields)
9 {
10 comboboxFieldNames.Items.Add(f.Name);
11 //MessageBox.Show(f.Name);
12 }
13 }
14}
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.
|
Peter Hull
Member #1,136
March 2001
|
LennyLen said: 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
|
LennyLen
Member #5,313
December 2004
|
Peter Hull said: 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.
|
Bruce Perry
Member #270
April 2000
|
The second problem you reported: I assume the exception is being thrown from inside the Add function, with a check along the lines of 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. -- |
LennyLen
Member #5,313
December 2004
|
Bruce Perry said: 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.
|
Bruce Perry
Member #270
April 2000
|
LennyLen said: 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. Quote: 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...? -- |
LennyLen
Member #5,313
December 2004
|
Bruce Perry said: 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.
|
bamccaig
Member #7,536
July 2006
|
Edgar Reynaldo said: 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). -- acc.js | al4anim - Allegro 4 Animation library | Allegro 5 VS/NuGet Guide | Allegro.cc Mockup | Allegro.cc <code> Tag | Allegro 4 Timer Example (w/ Semaphores) | Allegro 5 "Winpkg" (MSVC readme) | Bambot | Blog | C++ STL Container Flowchart | Castopulence Software | Check Return Values | Derail? | Is This A Discussion? Flow Chart | Filesystem Hierarchy Standard | Clean Code Talks - Global State and Singletons | How To Use Header Files | GNU/Linux (Debian, Fedora, Gentoo) | rot (rot13, rot47, rotN) | Streaming |
LennyLen
Member #5,313
December 2004
|
bamccaig said: 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 - https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/structs said: A struct can be used as a nullable type and can be assigned a null value.
|
bamccaig
Member #7,536
July 2006
|
LennyLen said: 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 - https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/structs said: A struct can be used as a nullable type and can be assigned a null value.
That's a very misleading statement. 1using System;
2
3namespace Application
4{
5 class Program
6 {
7 static int Main(string[] args)
8 {
9 Foo foo = null;
10
11 return 0;
12 }
13 }
14
15 struct Foo
16 {
17 }
18}
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>`. 1using System;
2
3namespace Application
4{
5 class Program
6 {
7 static int Main(string[] args)
8 {
9 Foo? foo1 = null;
10 Nullable<Foo> foo2 = null;
11 var foo3 = (Foo?)new Foo(); // Cast Foo to Nullable<Foo> (Foo?).
12 Foo foo4 = foo3.Value; // Access value of Nullable<T>.
13 Foo foo5 = (Foo)foo3; // Cast Nullable<T> back to T.
14
15 return 0;
16 }
17 }
18
19 struct Foo
20 {
21 }
22}
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. -- acc.js | al4anim - Allegro 4 Animation library | Allegro 5 VS/NuGet Guide | Allegro.cc Mockup | Allegro.cc <code> Tag | Allegro 4 Timer Example (w/ Semaphores) | Allegro 5 "Winpkg" (MSVC readme) | Bambot | Blog | C++ STL Container Flowchart | Castopulence Software | Check Return Values | Derail? | Is This A Discussion? Flow Chart | Filesystem Hierarchy Standard | Clean Code Talks - Global State and Singletons | How To Use Header Files | GNU/Linux (Debian, Fedora, Gentoo) | rot (rot13, rot47, rotN) | Streaming |
Audric
Member #907
January 2001
|
bamccaig said: 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 ! |
Bruce Perry
Member #270
April 2000
|
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). -- |
|