This question already has answers here:
What is a NullReferenceException, and how do I fix it?
(27 answers)
Closed 7 years ago.
I am writing a LINQ query. But, i am getting null object reference error for Model.StudentSummary.StudentDetails.
I put breakpoint on following foreach and when i mouse over Model.StudentSummary.StudentDetails i see StudentDetails is null.
I have initialized the whole model class than why it didn't initialize List<StudentDetails> in StudentSummary class?
foreach (Summary summary in Model.summaryData)
{
Model.StudentSummary.StudentDetails.Add(new SafetyDetails
{
Name = summary.Name,
ManTimeWorked = summary.TotalTime,
});
}
Model.cs
public class Report : BaseReportModel
{
public Report()
{
StudentSummary = new StudentSummary();
}
public StudentSummary StudentSummary { get; set; }
}
public class StudentSummary
{
public string Name { get; set; }
public List<StudentDetails> StudentDetails { get; set; }
}
Just because you initialized the object doesn't mean that all of its properties are initialized: each of those carries its default value until you change it, and the default for a List (or any class-type object) is null (more details in this post). You need to initialize the list.
You can inline this in your Report constructor like:
public class Report : BaseReportModel
{
public Report()
{
StudentSummary = new StudentSummary
{
StudentDetails = new List<StudentDetails>()
}
}
public StudentSummary StudentSummary { get; set; }
}
Another option is to initialize it in StudentSummary's constructor itself, which keeps the class in a nice state from the beginning without any additional work:
public class StudentSummary
{
public StudentSummary()
{
StudentDetails = new List<StudentDetails>();
}
public string Name { get; set; }
public List<StudentDetails> StudentDetails { get; set; }
}
This has a tradeoff: if you already have a List<StudentDetails> that you want to initialize it to, you needlessly create a new list - but if your regular use case is adding them as you do in the example code, it shouldn't be an issue.
If you're expecting StudentSummary.StudentDetails to be instantiated at the same time as StudentSummary you need to manually do it in the StudentSummary constructor, as you do with the StudentSummary in the Report constructor.
Related
This question already has answers here:
What is a NullReferenceException, and how do I fix it?
(27 answers)
Closed 5 years ago.
I'm new to c sharp. I"ve got an ASP.NET MVC Core 2.0 project and I need to populate a list inside a model and return that model to the page. My model looks like this:
public class PageModel
public string Title {get; set;}
public List<ChartGroups> Chart { get; set; }
}
public class ChartGroups
{
public string Freq { get; set; }
public string Head { get; set; }
}
To populate this I've got the following:
public PageModel GetChart(){
PageModel R = new PageModel();
R.Title = "Some Title";
R.Chart.Add(New ChartGroups {Freq ="Test", Head="Test2"});
R.Chart.Add(New ChartGroups {Freq ="Test3", Head="Test4"});
return(R);
}
The problem is I get an error saying I need to obstinate the object when I get to the R.Chart.Add... line. I've been doing this with drop down list and it works just fine....I'm sure I'm missing something simple just can't see it.
UPDATE:
I know that I need to obstinate the object, just not sure how to do so under this context.
You need to create an instance of the List<ChartGroups>() before you can start adding items to it. You can either do this in your GetChart() method:
public PageModel GetChart()
{
PageModel R = new PageModel();
R.Title = "Some Title";
R.Chart = new List<ChartGroups>(); //< ---
R.Chart.Add(New ChartGroups { Freq = "Test", Head = "Test2"});
R.Chart.Add(New ChartGroups { Freq = "Test3", Head = "Test4"});
return R;
}
Or in your PageModel class:
public class PageModel
{
public string Title { get; set; }
public List<ChartGroups> Chart { get; set; } = new List<ChartGroups>();
}
You need to Initialize the List. So for example, in your PageModel constructor you can do:
public class PageModel
{
public PageModel()
{
Chart = new List<ChartGroups>();
}
public string Title {get; set;}
public List<ChartGroups> Chart { get; set; }
}
Just to inform, you don't probably need the { set; } part of the Chart property since you are now initializing the property in the constructor, so you can just put it as
public List<ChartGroups> Chart { get; }
And then, if you wish, you can also you syntax like
public List<ChartGroups> Chart { get; } = new List<ChartGroups>();
Which would allow you to move the initialization out of the constructor.
Your list is null. So set it to an instance:
public List<ChartGroups> Chart { get; set; } = new List<ChartGroups>()
This question already has answers here:
What is a NullReferenceException, and how do I fix it?
(27 answers)
Closed 6 years ago.
I´m attempting to fill a POCO object but I get the NullReferenceException - Object reference not set to an instance of an object, at line "objectAreas.position.Add(objectPositions);" I think I'm not initializing well but I don't see my mistake, let's see the code:
POCO OBJECT
public class GenericQuery
{
public sealed class Areas
{
public int idarea { get; set; }
public string areaname { get; set; }
public List<Positions> positions { get; set; }
}
public sealed class Positions
{
public int idposition { get; set; }
public string positionname { get; set; }
}
public sealed class QueryAreasPositions
{
public int code { get; set; }
public string response { get; set; }
public List<Areas> areas { get; set; }
}
}
Filling It
GenericQuery.QueryAreasPositions objectAreasPositions = new GenericQuery.QueryAreasPositions();
var query = areaRepository.Get(); //Eager Loading EntityFramework List Object, see the AreaRepository at the end
objectAreasPositions.code = 123;
objectAreasPositions.response = "anything";
foreach (var area in query)
{
GenericQuery.Areas objectAreas = new GenericQuery.Areas();
objectAreas.idarea = area.IdArea;
objectAreas.areaname = area.Name;
foreach (var position in area.Position)
{
GenericQuery.Positions objectPositions = new GenericQuery.Positions();
objectPositions.idposition = position.IdPosition;
objectPositions.positionname = position.Name;
***objectAreas.position.Add(objectPositions);***//HERE
}
objectAreasPositions.areas.Add(objectAreas); //And maybe here
}
AreaRepository
public List<Area> Get()
{
using (var context = new Entities())
{
return context.Area.Include("Position").ToList();
}
}
I would appreciate any help/guide you can give me, Thanks.
You are never initializing objectAreas.position, hence the default value for a List<T> is null.
Since you are trying to call the Add method on a null reference, you are getting a NullReferenceException.
To fix this, you should initialize the property before using it:
objectAreas.position = new List<GenericQuery.Positions>();
Alternatively, you can add this logic on GenericQuery.Areas constructor, which would be more appropriate:
public sealed class Areas
{
public int idarea { get; set; }
public string areaname { get; set; }
public List<Positions> positions { get; set; }
public class Areas()
{
positions = new List<Positions>();
}
}
Shouldn't you rather be doing like below. Your position is null cause not yet initialized and thus the said exception.
objectAreas.position = new List<Position>();
objectAreas.position.Add(objectPositions);
I have this situation:
List<Details> trace;
private class Details
{
public string date { get; set; }
public string type { get; set; }
public string mex { get; set; }
}
private class Context
{
public List<object> context { get; set; }
}
how can I insert in the trace list the class Details and Context? My goal is create a multidimensional list that have as key the class properties such as: date, type, mex, context and as value a dynamic content.
You can use for that purpose an abstraction contract between both classes...
for example if both classes implement a new interface, lets say MyCustomInterface that you define, then declare the list as List<MyCustomInterface> trace; and then you can add objects of both classes...
Example:
List<MyCustomInterface> trace;
private class Details: MyCustomInterface
{
public string date { get; set; }
public string type { get; set; }
public string mex { get; set; }
}
private class Context:MyCustomInterface
{
public List<object> context { get; set; }
}
then you can always do
trace.Add(new Context(...));
trace.Add(new Details(...));
You can use Tuple<Details, Context> to hold instance of either as item in the list, but then when iterating items you will then have to use Item1 and such names to access underlying values:
List<Tuple<Details, Context>> trace;
// add
trace.Add(new Tuple(new Details(), new Context()));
// iterate
foreach(var item in trace)
if(item.Item1?.date == ... && item.Item2?.context != null) { ... }
A better idea might be to construct own type to hold both: Details and Context instance (as properties with same names):
class ContextDetails
{
public Context { get; set; }
public Details { get; set; }
// todo: add constructor to simplify constructing items when adding
}
and use it
List<ContextDetails> trace;
// add
trace.Add(new ContextDetails()
{
Details = new Details(),
Context = new Context(),
});
// iterate
foreach(var item in trace)
if(item.Details?.date == ... && item.Context?.context != null) { ... }
Hmm if you really wanted to have both in a List, i'd give you two options:
First:
Create a parent-Class which both inherit.
Next step is to put the name of the parent class into your List.
Both will fit if they were extended by the same parent class
Second:
Create an Objekt that contains a Context and Details object and put that into the list.
This question already has answers here:
What is a NullReferenceException, and how do I fix it?
(27 answers)
Closed 7 years ago.
i have a problem, i created an object in C# like this:
public class logis
{
public string codigo { get; set; }
public List<decimal> Necesidades { get; set; }
decimal SumaNecesidades{get;set;}
}
then i do something like this:
logisva logi = new logis();
logi.codigo = oDataReader.GetValue(0).ToString();
logi.Necesidades.Add(0);
But when i execute my code i get a null reference exception error. Object reference not set to an instance of an object. on the last line logi.Necesidades.Add(0);
Any idea why i get this error?
In C# the properties do not initialize/create the List<ofType> object automatically. You need to create the list explicitely:
public class logis
{
public string codigo { get; set; }
public List<decimal> Necesidades { get; set; }
decimal SumaNecesidades{get;set;}
public logis()
{
this.Necesidades = new List<decimal>();
}
}
Another option is to create the list in the getter resp. setter (so to say your own lazy initialization, downside - introduces more code, advantage no need to override every contructor):
public class logis
{
public string codigo { get; set; }
decimal SumaNecesidades{get;set;}
private List<decimal> necesidades = null;
private void initNecesidades()
{
if (this.necesidades == null)
{
this.necesidades = new List<decimal>();
}
}
public List<decimal> Necesidades
{
get
{
this.initNecesidades();
return this.necesidades;
}
set
{
this.initNecesidades();
this.necesidades = value;
}
}
}
Yet another option would be to use the new C# 6.0 features (if it is an option to use/already using the latest .NET Framework version) as already suggested in the comments by #Jcl:
public List<decimal> Necesidades { get; set; } = new List<decimal>()
I'm trying to figure out what the proper syntax is to achieve a certain API goal, however I am struggling with visibility.
I want to be able to access a Messenger instance's member like msgr.Title.ForSuccesses.
However, I do not want to be able to instantiate Messenger.Titles from outside my Messenger class.
I'm also open to making Messenger.Titles a struct.
I'm guessing I need some sort of factory pattern or something, but I really have no idea how I'd go about doing that.
See below:
class Program {
static void Main(string[] args) {
var m = new Messenger { Title = { ForErrors = "An unexpected error occurred ..." } }; // this should be allowed
var t = new Messenger.Titles(); // this should NOT be allowed
}
}
public class Messenger {
// I've tried making this private/protected/internal...
public class Titles {
public string ForSuccesses { get; set; }
public string ForNotifications { get; set; }
public string ForWarnings { get; set; }
public string ForErrors { get; set; }
// I've tried making this private/protected/internal as well...
public Titles() {}
}
public Titles Title { get; private set; }
public Messenger() {
Title = new Titles();
}
}
You just need to make Titles private and expose an interface instead of it.
class Program {
static void Main(string[] args) {
var m = new Messenger { Title = { ForErrors = "An unexpected error occurred ..." } }; // this is allowed
var t = new Messenger.Titles(); // this is NOT allowed
}
}
public class Messenger {
public interface ITitles {
string ForSuccesses { get; set; }
string ForNotifications { get; set; }
string ForWarnings { get; set; }
string ForErrors { get; set; }
}
private class Titles : ITitles {
public string ForSuccesses { get; set; }
public string ForNotifications { get; set; }
public string ForWarnings { get; set; }
public string ForErrors { get; set; }
}
public ITitles Title { get; private set; }
public Messenger() {
Title = new Titles();
}
}
If you make the Titles constructor internal you will be able to create instances of it within your assembly only. If it is an API, perhaps that will be protected enough? You can see this pattern within the BCL (such as HttpWebRequest that can be created only through calls to WebRequest.Create).
Why Would I Ever Need to Use C# Nested Classes Nested type is never intended to be initialized from external type.
Well, you could make Titles a struct and make the constructor either public or internal. In that way, every time a client gets a copy of the Titles instance through the Title property, they will be getting the value, not the reference. They could modify that value, but to apply that change to the internal state of your object, they would need to be able to set the value back again through the Title property. They can't, because you have the Title setter marked private.
You will have to do the same when you change a value internally. For example:
// Your constructor...
public Messenger()
{
Titles t = new Titles();
t.ForSuccesses = "blah";
Title = t;
}
You can do this internally because you have access to the private setter for the Title property.
The main downside is that it might confuse the clients of your framework a bit because it looks like you can set the values of the Titles instance, but there is no real way for them to commit that change back to the Messenger class.