Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » Any C# coders? I need some help

Credits go to Edgar Reynaldo and jmasterx for helping out!
This thread is locked; no one can reply to it. rss feed Print
Any C# coders? I need some help
LennyLen
Member #5,313
December 2004
avatar

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

#SelectExpand
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
Member #8,592
May 2007
avatar

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(...);
}

jmasterx
Member #11,410
October 2009

yes an array in c# is just an array of pointers for reference types

Edgar Reynaldo
Member #8,592
May 2007
avatar

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.

Chris Katko
Member #1,881
January 2002
avatar

You can do that in D. ;D

-----sig:
“Programs should be written for people to read, and only incidentally for machines to execute.” - Structure and Interpretation of Computer Programs
"Political Correctness is fascism disguised as manners" --George Carlin

LennyLen
Member #5,313
December 2004
avatar

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
avatar

Since you were all so helpful, here's another little problem I've run into. I have another function as follows:

#SelectExpand
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 ;D

LennyLen
Member #5,313
December 2004
avatar

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
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.

--
Bruce "entheh" Perry [ Web site | DUMB | Set Up Us The Bomb !!! | Balls ]
Programming should be fun. That's why I hate C and C++.
The brxybrytl has you.

LennyLen
Member #5,313
December 2004
avatar

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...?

--
Bruce "entheh" Perry [ Web site | DUMB | Set Up Us The Bomb !!! | Balls ]
Programming should be fun. That's why I hate C and C++.
The brxybrytl has you.

LennyLen
Member #5,313
December 2004
avatar

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
avatar

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 &lt; 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).

LennyLen
Member #5,313
December 2004
avatar

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
avatar

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.

Nullable.cs#SelectExpand
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>`.

Nullable2.cs#SelectExpand
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.

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).

--
Bruce "entheh" Perry [ Web site | DUMB | Set Up Us The Bomb !!! | Balls ]
Programming should be fun. That's why I hate C and C++.
The brxybrytl has you.

Go to: