This question already has answers here:
What is a NullReferenceException, and how do I fix it?
(27 answers)
Closed 5 years ago.
I have a class that looks something like this:
public class Parent
{
private string sFirst_name1;
public string sParent1FirstName
{
get { return sFirst_name1; }
set { sFirst_name1 = value; }
}
private string sLast_name1;
public string sParent1LastName
{
get { return sLast_name1; }
set { sLast_name1 = value; }
}
private List<int> lChild_ID;
public List<int> lChildID
{
get { return lChild_ID; }
set { lChild_ID = value; }
}
public Parent(string sP1FN, string sP1LN, List<int> lCID)
{
lChild_ID= new List<int>();
sFirst_name1 = sP1FN;
sLast_name1 = sP1LN;
lChild_ID = lCID;
}
I create an instance of the class and add it to a List of type Parent with the line:
lParents.Add(new Parent(sParent1FNTemp, sParent1LNTemp,lParentChildIDTemp));
Where lParentChildIDTemp is just a null integer List.
Later on, I am trying to update the int list of the object at a specified index by saying:
lParents[iIndex].lChildID.Add(++iIDCounters);
And I get a null reference exception. I'm not too sure why, but I think it has something to do with my constructor for my class. The weird thing is, I have another class that does pretty much the same thing but it doesn't throw the exception. If anyone has any clues, I would be greatful.
Give your property is null, you should make sure you are not access null values to call methods or properties. If you do that, you will get an NullReferenceException. Try this:
var childIds = lParents[iIndex].lChildID;
if (childIds != null)
{
childIds.Add(++iIDCounters);
}
In your constructor, you could check the if the argument is null and define a default list int. If you for to set the argument, even if it is null, you will get null.
public Parent(string sP1FN, string sP1LN, List<int> lCID)
{
sFirst_name1 = sP1FN;
sLast_name1 = sP1LN;
if (lCID == null)
{
lChild_ID = new List<int>();
}
else
{
lChild_ID = lCID;
}
}
Since apparently you want to be able to pass in the lChildID during construction, change the constructor as so:
public Parent(string sP1FN, string sP1LN, List<int> lCID) {
sFirst_name1 = sP1FN;
sLast_name1 = sP1LN;
lChild_ID = lCID ?? new List<int>();
}
Drop the List of int argument in the ctor and why not use auto props:
public class Parent
{
public Parent(string sP1FN, string sP1LN)
{
LChildID = new List<int>();
sFirst_name1 = sP1FN;
sLast_name1 = sP1LN;
}
public List<int> LChildID { get; set; }
If you're not familiar with auto-implemented properties, see https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/auto-implemented-properties
Plus, you could also overload the ctor:
public Parent(string sP1FN, string sP1LN, List<int> lCID)
{
LChildID = lCID;
sFirst_name1 = sP1FN;
sLast_name1 = sP1LN;
}
Related
Let us suppose we have a class like below :-
class DoubleLinkedListNode
{
public int Value { get; set; }
public DoubleLinkedListNode(int value)
{
Value = value;
}
public DoubleLinkedListNode next = null;
public DoubleLinkedListNode prev = null;
}
And then we create a dictionary as given below :-
IDictionary<int, DoubleLinkedListNode> dict = new Dictionary<int, DoubleLinkedListNode>();
The key of the dictionary will hold the Value of the DoubleLinkedListNode that it contains like this :-
DoubleLinkedListNode newNode = new DoubleLinkedListNode(value);
dict.Add(newNode.Value, newNode );
Let us also create a function which takes the type of the value of the dictionary as input and we make that value null inside the body of the function as shown below :-
private void RemoveNode(DoubleLinkedListNode nodeToBeRemoved)
{
if(nodeToBeRemoved != null)
{
//Do Something
nodeToBeRemoved = null;
}
}
and we call the function like this :-
RemoveNode(dict[someValue]);
Let us create another function in which we make the value null explicitly as shown below :-
private void RemoveNodeAnother(DoubleLinkedListNode nodeToBeRemoved)
{
if(nodeToBeRemoved != null)
{
//Do Something
dict[nodeToBeRemoved.Value] = null;
}
}
And then we call the function like this :-
RemoveNodeAnother(dict[someValue]);
What is the difference between the above two functions ?
Why I am asking is this I was doing this question on Leetcode. The solution that I wrote is as follows :-
public class FirstUnique
{
private class DoubleLinkedListNode
{
public int Value { get; set; }
public DoubleLinkedListNode(int value)
{
Value = value;
}
public DoubleLinkedListNode next = null;
public DoubleLinkedListNode prev = null;
}
DoubleLinkedListNode dummyHeadNode = new DoubleLinkedListNode(-1);
DoubleLinkedListNode dummyTailNode = new DoubleLinkedListNode(-1);
IDictionary<int, DoubleLinkedListNode> dict = new Dictionary<int, DoubleLinkedListNode>();
public FirstUnique(int[] nums)
{
InitialiseDummyHeadAndTailNodes();
foreach(int i in nums)
{
Add(i);
}
}
public int ShowFirstUnique()
{
return dummyHeadNode.next.Value;
}
public void Add(int value)
{
if (dict.ContainsKey(value))
{
RemoveNode(dict[value]);
}
else
{
DoubleLinkedListNode newNode = new DoubleLinkedListNode(value);
AddNode(newNode);
}
}
private void InitialiseDummyHeadAndTailNodes()
{
dummyHeadNode.next = dummyTailNode;
dummyTailNode.prev = dummyHeadNode;
}
private void RemoveNode(DoubleLinkedListNode nodeToBeRemoved)
{
if(nodeToBeRemoved != null)
{
nodeToBeRemoved.prev.next = nodeToBeRemoved.next;
nodeToBeRemoved.next.prev = nodeToBeRemoved.prev;
// If I write nodeToBeRemoved = null, the solution won't pass.
// But if I write dict[nodeToBeRemoved.Value] = null, the solution is accepted.
dict[nodeToBeRemoved.Value] = null;
}
}
private void AddNode(DoubleLinkedListNode nodeToBeAdded)
{
//Update the pointers.
nodeToBeAdded.prev = dummyTailNode.prev;
nodeToBeAdded.prev.next = nodeToBeAdded;
nodeToBeAdded.next = dummyTailNode;
dummyTailNode.prev = nodeToBeAdded;
//Add the node to the dictionary.
dict.Add(nodeToBeAdded.Value, nodeToBeAdded);
}
}
I have made the comments where the anomaly lies. What could be the reason for this behavior ?
There is only one way to "set dictionary value to null" -
dictionary[key] = null;
indeed, if key is not there you need to add it first... Which leads to the way to set value to null -
if (dictionary.ContainsKey(key))
dictionary[key] = null;
else
dictionary.Add(key, null);
Note that setting value to null has zero impact on what was stored there previously.
I'm trying to edit an enum value in a class instance based on whether that instance appears in a dictionary of type <string, myClass>. What seems logical to me is to do the code snippets below:
if (pumpDict.ContainsKey(ID))
{
foreach(KeyValuePair<string, PumpItem> kvp in pumpDict)
{
if(kvp.Key == ID)
{
kvp.Value.state = kvp.Value.state.Available; //error here
kvp.Value.fuelPumped = fuelPumped;
kvp.Value.fuelCost = fuelCost;
break;
}
}
}
else
{
PumpItem pump = new PumpItem();
pumpDict.Add(ID, pump);
}
And my PumpItems class is such:
namespace PoSClientWPF
{
public enum pumpState
{
Available,
customerWaiting,
Pumping,
customerPaying
};
public enum fuelSelection
{
Petrol,
Diesel,
LPG,
Hydrogen,
None
};
class PumpItem
{
public double fuelPumped;
public double fuelCost;
public fuelSelection selection;
public pumpState state;
public PumpItem()//intialize constructor
{
this.fuelPumped = 0;
this.fuelCost = 0;
this.selection = fuelSelection.None;
this.state = pumpState.Available;
}
}
}
I was led to believe that to have an enum value in a constructor, they have to be set up as above, with a new instance of those enums declared in the class body.
It seems to me, that what I'm trying to do is logical but I am getting an error on the right hand side of the assignation which states:
"member PoSClientWPF.pumpState.Available cannot be accessed with an instance reference; qualify is with a type name instead"
I've searched for this error among several forums but only seem to find errors involving calling static variables incorrectly. Can anyone point me in the direction of a solution?
Thanks in advance.
You are incorrectly accessing the Enum member:
// this is incorrect
kvp.Value.state = kvp.Value.state.Available; //error here
// this is the correct way
kvp.Value.state = PoSClientWPF.pumpState.Available;
You know you have a dictionary?
PumpItem pumpItem = pumpDict[ID];
pumpItem.state = PoSClientWPF.pumpState.Available;
or
PumpItem pumpItem;
if (pumpDict.TryGetValue(ID, out pumpItem))
{
pumpItem.state = PoSClientWPF.pumpState.Available;
}
else
{
pumpItem = new PumpItem();
pumpDict.Add(ID, pumpItem);
}
Could just add ID to PumpItem and use a List
PumpItem pumpItem = pumpList.FirstOrDefualt(x => x.ID == ID)
if (pumpItem == null)
pumpList.Add(new PumpItem(ID));
else
pumpItem.state = PoSClientWPF.pumpState.Available;
class PumpItem
{
public double fuelPumped = 0;
public double fuelCost = 0;
public fuelSelection selection = fuelSelection.None;
public pumpState state = pumpState.Available;
public Int32? ID = null;
public PumpItem()//intialize constructor
{ }
public PumpItem(Int32? ID)
{
this.ID = ID;
}
}
This question already has answers here:
What is a NullReferenceException, and how do I fix it?
(27 answers)
Closed 7 years ago.
I have built a simple code as shown below. While debugging, I am getting an error about "NullReference Handled Exception" at the code line:
X.DataPoints.Add(dp);
Here is the code snippet. Please advice on what am I missing?
public class RankPlot
{
public List<RankPlotDataPoint> DataPoints { get; set; }
}
public class RankPlotDataPoint
{
public double RankVal { get; set; }
public double ProbVal { get; set; }
}
ObservableCollection<RankPlot> EURresults = new ObservableCollection<RankPlot>();
public ObservableCollection<RankPlot> EURResults
{
get { return EURresults; }
set
{
EURresults = value;
base.OnPropertyChanged("StringList");
}
}
public void evaluate()
{
RankPlot X = new RankPlot();
for (double i = 0; i<5; i++)
{
RankPlotDataPoint dp = new RankPlotDataPoint();
dp.RankVal =i+1; // Y axis
dp.ProbVal = i; // X axis
X.DataPoints.Add(dp);
}
EURResults.Add(X);
}
You are getting Null Exception Because you need to initialize the List<RankPlotDataPoint> DataPoints. So Instead of Initialize DataPoints every time you create an instance of RankPlot, you should initialize like below:
Change your Below Statement:
public class RankPlot
{
public List<RankPlotDataPoint> DataPoints { get; set; }
}
To
public class RankPlot
{
public List<RankPlotDataPoint> DataPoints { get; set; } = new List<RankPlotDataPoint>();
}
in evaluate() method instead of
RankPlot X = new RankPlot();
write
RankPlot X = new RankPlot{DataPoints = new List<RankPlotDataPoint>()};
It'll initialize the list.
X.DataPoints = new List<RankPlotDataPoint>(); you never initialize the list before you add items to the list.
You are trying to add a value to a List<RankPlotData> that doesn't exist. With your property in the RankPlot class, you need to declare a new List of RankPlotData in your RankPlot class, and initialize it with .. new List<RankPlotData>(). Then, you should return that from your property get accessor.
This question already has answers here:
What is a NullReferenceException, and how do I fix it?
(27 answers)
Closed 10 years ago.
I have xml code that would be something like this:
file named: player.xml
<root>
<person>
<fname>Dwight</fname>
<lname>Howard</lname>
<vertLeap>
<try1>32.33</try1>
<try2>33.33</try2>
<try3>34.33</try3>
</vertLeap>
</person>
<person>
<fname></fname>
<lname>Jordan</lname>
<vertLeap>
<try1>40.33</try1>
</vertLeap>
</person>
</root>
This isn't my real xml, but should work for the example.
Now I want to use linq to xml to read the data. Iam am trying like this.
Class:
public class Player
{
public string FirstName { get; set; }
public string LastName { get; set; }
public int Leap1 { get; set; }
public int Leap2 { get; set; }
public int Leap3 { get; set; }
public WritePlayertoDatabase()
{
//do stuff to write
}
}
Query:
XDocument xDoc = XDocument.Load("player.xml");
var player_query = from p xDoc.Desendants("person")
select new Player
{
FirstName = p.Element("fname"),
LastName = p.Element("lname"),
Leap1 = p.Element("try1"),
Leap2 = p.Element("try2"),
Leap3 = p.Element("try3")
};
I'm getting a NullReferenceException. Is there a way to test if the elements exist before I try to use the value? Or is there a way better way to accomplish this?
So there are a few things wrong with your linq query.
1) p.Element("fname") will return the fname XML Element, not a string. So you still need to get the element's value. Similarly, the Leap1-3 properties are int, but you will get the element value as a stirng and need to convert it. But, try1-3 are not ints in the xml, so you probably want to change the type to somehting else in the Player class.
2) try1 - tryx element s are all children of 'vertleap'. You can't directly get element 'try1' from 'person'. It will be null.
So how about something more like this:
var player_query = from p in xDoc.Descendants("person")
select new Player
{
FirstName = p.Element("fname") != null ? p.Element("fname").Value : "",
LastName = p.Element("lname") != null ? p.Element("lname").Value : "",
Leap1 = p.Element("vertLeap") != null ? (p.Element("vertLeap").Element("try1") != null ? Decimal.Parse(p.Element("vertLeap").Element("try1").Value) : 0) : 0,
Leap2 = p.Element("vertLeap") != null ? (p.Element("vertLeap").Element("try2") != null ? Decimal.Parse(p.Element("vertLeap").Element("try2").Value) : 0) : 0,
Leap3 = p.Element("vertLeap") != null ? (p.Element("vertLeap").Element("try3") != null ? Decimal.Parse(p.Element("vertLeap").Element("try3").Value) : 0) : 0,
};
Using the XML you posted, the p.Element("try<X>") calls will ALWAYS return nulll... as I see #SimonC has just pointed out. You'll need to tunnel down the XML tree to get the value out, or use Descendants("try<x>").FirstOrDefault() to get the first descendant with a matching name. This may still be null, which leads us back to the real point of the question.
The issue really is that you are trying to perform an operation on an object which may not exist. Apart from the conditional sequence that #SimonC suggested, you can use helper methods or extensions to detect a missing element and provide a meaningful default value.
public static string AsString(this XElement self)
{
if (self == null)
return null;
return self.Value;
}
public static double AsDouble(this XElement self, double defValue = default(double))
{
if (self == null)
return defValue;
double res = defValue;
try { res = (double)self; }
catch { }
return res;
}
public static int AsInt(this XElement self, int defValue = default(int))
{
if (self == null)
return defValue;
double res = defValue;
try { res = (double)self; }
catch { }
return (int)res;
}
Then your Linq query becomes:
var player_query = from p in xDoc.Descendants("person")
select new Player
{
FirstName = p.Element("fname").AsString(),
LastName = p.Element("lname").AsString()
Leap1 = p.Descendants("try1").FirstOrDefault().AsInt(),
Leap2 = p.Descendants("try2").FirstOrDefault().AsInt(),
Leap3 = p.Descendants("try3").FirstOrDefault().AsInt()
};
If there is no 'try1' node within the 'player' node's descendants, the FirstOrDefault() method will return null. The AsInt() extension method is then called with a null this reference, which it detects and returns default(int) instead of throwing an exception.
You could also write a bunch of ConvertElementToXXX(elem, defValue) methods, but I think this is a reasonably valid use of extensions. It's just a shame that XElement doesn't implement IConvertible.
I know I went overboard with this quesiton, but after fiddling around with it I decided to re-write your example with XmlSerialization instead. Depending on your needs, I would highly recommend you serialize your data into objects, and pass these around.
You will need the using using System.Xml.Serialization; namespace, but I wrote the below complete program if you want to use any of it.
public class Program
{
[XmlRoot("root")]
public class Team
{
private List<Player> players = new List<Player>();
[XmlElement("player")]
public List<Player> Players { get { return this.players; } set { this.players = value; } }
// serializer requires a parameterless constructor class
public Team() { }
}
public class Player
{
private List<int> verticalLeaps = new List<int>();
[XmlElement]
public string FirstName { get; set; }
[XmlElement]
public string LastName { get; set; }
[XmlElement]
public List<int> vertLeap { get { return this.verticalLeaps; } set { this.verticalLeaps = value; } }
// serializer requires a parameterless constructor class
public Player() { }
}
static public void Main(string[] args)
{
Program myProgram = new Program();
myProgram.WritePlayertoDatabase();
myProgram.ReadPlayerDatabase();
}
public void WritePlayertoDatabase()
{
Player p1 = new Player() { FirstName = "dwight", LastName = "howard", vertLeap = new List<int>() { 1, 2, 3 } };
Player p2 = new Player() { FirstName = "dwight", LastName = "howard", vertLeap = new List<int>() { 1 } };
Team players = new Team();
players.Players.Add(p1);
players.Players.Add(p2);
XmlSerializer serializer = new XmlSerializer(typeof(Team));
using (TextWriter textWriter = new StreamWriter(#"C:\temp\temp.txt"))
{
serializer.Serialize(textWriter, players);
textWriter.Close();
}
}
public void ReadPlayerDatabase()
{
Team myTeamData = new Team();
XmlSerializer deserializer = new XmlSerializer(typeof(Team));
using (TextReader textReader = new StreamReader(#"C:\temp\temp.txt"))
{
myTeamData = (Team)deserializer.Deserialize(textReader);
textReader.Close();
}
}
}
How do I find and replace a property using Linq in this specific scenario below:
public interface IPropertyBag { }
public class PropertyBag : IPropertyBag
{
public Property[] Properties { get; set; }
public Property this[string name]
{
get { return Properties.Where((e) => e.Name == name).Single(); }
//TODO: Just copying values... Find out how to find the index and replace the value
set { Properties.Where((e) => e.Name == name).Single().Value = value.Value; }
}
}
Thanks for helping out in advance.
Do not use LINQ because it will not improve the code because LINQ is designed to query collection and not to modify them. I suggest the following.
// Just realized that Array.IndexOf() is a static method unlike
// List.IndexOf() that is an instance method.
Int32 index = Array.IndexOf(this.Properties, name);
if (index != -1)
{
this.Properties[index] = value;
}
else
{
throw new ArgumentOutOfRangeException();
}
Why are Array.Sort() and Array.IndexOf() methods static?
Further I suggest not to use an array. Consider using IDictionary<String, Property>. This simplifies the code to the following.
this.Properties[name] = value;
Note that neither solution is thread safe.
An ad hoc LINQ solution - you see, you should not use it because the whole array will be replaced with a new one.
this.Properties = Enumerable.Union(
this.Properties.Where(p => p.Name != name),
Enumerable.Repeat(value, 1)).
ToArray();
[note: this answer was due to a misunderstanding of the question - see the comments on this answer. Apparently, I'm a little dense :(]
Is your 'Property' a class or a struct?
This test passes for me:
public class Property
{
public string Name { get; set; }
public string Value { get; set; }
}
public interface IPropertyBag { }
public class PropertyBag : IPropertyBag
{
public Property[] Properties { get; set; }
public Property this[string name]
{
get { return Properties.Where((e) => e.Name == name).Single(); }
set { Properties.Where((e) => e.Name == name).Single().Value = value.Value; }
}
}
[TestMethod]
public void TestMethod1()
{
var pb = new PropertyBag() { Properties = new Property[] { new Property { Name = "X", Value = "Y" } } };
Assert.AreEqual("Y", pb["X"].Value);
pb["X"] = new Property { Name = "X", Value = "Z" };
Assert.AreEqual("Z", pb["X"].Value);
}
I have to wonder why the getter returns a 'Property' instead of whatever datatype .Value, but I'm still curious why you're seeing a different result than what I am.