Adding thing to list in object in c# - c#

I'm trying to add a string to an object in c# like this:
The class is:
class thing
{
public int somenumber { get; set; }
public int someothernumber { get; set; }
public List<string> words { get; set; }
}
I'm trying to do
var something = new thing();
something.words.Add("some word");
How do I add a string to the list 'words' without getting nullreference-errors?

Initialize words list in the constructor of the class, to make sure that it will exist.
public YourClass {
words = new List<string>;
}
Add new item to that list in the corresponding method.
public void YourMethod {
words.Add("New Item");
}

You have first to create a list, since by default words would be null.
var something = new thing();
something.words = new List<string>();
Then you can use the newly created list, as you have already done:
something.words.Add("some word");
Now when something.words would point to the newly created list and it wouldn't be null.
Another more consistent way to do this, is to create that list in the class constructor:
public class Thing
{
public int SomeNumber { get; set; }
public int SomeOtherNumber { get; set; }
public List<string> Words { get; set; }
public Thing()
{
Words = new List<string>();
}
}
btw, please also look at the naming conventions (e.g. properties name start with capital letters as well as class names).
Update
As correctly matthew-watson mentioned in his comments, there is also another way (probably better) for doing the same thing:
public class Thing
{
public int SomeNumber { get; set; }
public int SomeOtherNumber { get; set; }
public List<string> Words { get; } = new List<string>();
}
Doing so, we create a read-only list. Essentially when we create an instance of this class a new list of strings is created and it's reference is assigned to the Words backing field. From that moment, you can't change the reference that is stored in that backing field and you can use the list only for adding/removing things, you can't change it's reference.

Related

Can you declare a List of a class within another class?

I am trying to create a simple order sheet that has products, customers, order lines, and an order sheet. Currently, I am just hardcoding in products and customers for simple testing purposes. With the order sheet, I want to have a List of the order line items (contains quantity and price from products, and a few other bits of information) in the order class. When I create the order in the program, it's not creating the List of order line items that I have in the constructor. I have tried to .Add within the constructor which didn't work as well in the program, in the program it states it does not contain the definition Add.
When I try to access .test it shows as NULL.
namespace ObjectsCSharpe.Library
class Order
{
public Order()
{
var testLine = new List<OrderLineItems>();
}
public List<OrderLineItems> testLine { get; set; }
}
class OrderLineItems
{
public OrderLineItems()
{
this.orderID = 0;
this.lineNumber = 0;
this.product = new Product();
this.quantity = 0;
this.test = "OLI";
this.lineTotal = 0.00;
}
public int orderID { get; set; }
public int lineNumber { get; set; }
public Product product { get; set; }
public int quantity { get; set; }
public string test { get; set; }
public double lineTotal { get; set; }
}
class Program
{
static void Main(string[] args)
{
Order orderSheet = new Order();
OrderLineItems temp456 = new OrderLineItems();
orderSheet.testLine.Add(temp456);
string abc = orderSheet.testLine[0].test;
Console.WriteLine(abc);
}
}
I'll start with this excerpt:
public Order()
{
var testLine = new List<OrderLineItems>();
}
This is the constructor for the Order type. In this code, the var keyword means you are declaring a new variable, where the scope of the variable is limited to that method. The type also contains this:
public List<OrderLineItems> testLine { get; set; }
So there is a separate testLine variable in the type. But, in the constructor, the use of var means this other variable was not touched.
Later on we have this code:
orderSheet.testLine.Add(temp456);
Unfortunately, because of the earlier mistake, orderSheet.testLine is still null, and you can't call a method on a null reference.
You can fix this as easily as removing var from the constructor:
public Order()
{
testLine = new List<OrderLineItems>();
}
or, even better, remove the entire constructor from the type completely. Initialize the list property where it is declared and make it get-only:
public class Order
{
public List<OrderLineItems> testLine {get;} = new List<OrderLineItems>();
}
(Note: You can still add items to get-only List property.)
I think you need to make public keyword while creating all your class.
public class Order{
//Add Your class declaration...
}

How do I build a new object that contains a List<string> as attribute?

So, in my main form class I have the following list, which is populated by user input:
List<string> ProduseAlese = new List<string>();
And after it's populated, it's going into this constructor:
Comenzi comanda = new Comenzi(nrCom, dataCom, dataLiv, factura, ProduseAlese);
And my class looks like this:
public class Comenzi
{
public int NrComanda { get; set; }
public DateTime DataComanda { get; set; }
public DateTime DataLivrare { get; set; }
public List<string> Articole { get; set; }
public Facturi Factura { get; set; }
public Comenzi(int nrcomanda, DateTime datacomanda, DateTime datalivrare, Facturi _factura, List<string> _articole)
{
NrComanda = nrcomanda;
DataComanda = datacomanda;
DataLivrare = datalivrare;
Factura = _factura;
}
}
What do I have to write in the constructor?
The point is to copy the items from the initial list into the newly created object.
If what you want is to copy the list objects into a new list, you can use the ToList() method from the System.Linq namespace.
Articole = _articole.ToList();
This should work:
public List<string> Articole { get; set; } = new List<string>();
public Facturi Factura { get; set; }
public Comenzi(int nrcomanda, DateTime datacomanda, DateTime datalivrare, Facturi _factura, List<string> _articole)
{
NrComanda = nrcomanda;
DataComanda = datacomanda;
DataLivrare = datalivrare;
Factura = _factura;
_articole = _articole?? new List<string>();
Articole.AddRange(_articole.ToArray());
}
Maybe you don't "have to" use the class constructor to feed all your object data, unless there is a requirement needing you to do so.
Since your properties are public you could asign a value to them after creating the object
Comenzi comanda = new Comenzi(nrCom, dataCom, dataLiv, factura);
comanda.Articole = ProduseAlese;
Keep in mind that as you're developing your application your class definition might grow and is not a good practice to fill ALL the properties in the constructor. You have to keep only the ones that are mandatory for your objects of that class.

C# - Using a model that contains a model of arrays

I have this model that I am trying to reference and get the an array of this type.
public class TestModel
{
public string Name { get; set; }
public Guid Id { get; set; }
public List<Conditions> Conditions { get; set; }
}
I also need to get the conditions for this which is a separate model with a few arrays.
public class Conditions
{
public List<string> Country { get; set; }
public List<int> Grades { get; set; }
public List<string> Disciplines { get; set; }
}
I can get the Name and Id easily enough but when I try and get the values in any of the arrays I get an error Object reference not set to an instance of an object. which it would normally give as the array is not instantiated. Is there any way to do this without instantiating the array?
Code I am using to get the Id
private static ArrayList GetTests()
{
Console.WriteLine("Get tests");
foreach (TestModel test in testModel)
{
var conditions = test.Conditions.Disciplines;
Console.WriteLine("");
Console.WriteLine("testID: " + test.Id);
}
return networks;
}
The model is populated in the main method:
private static IEnumerable<TestModel> testModel= new TestModel[] { };
public static void Main(string[] args)
{
Console.WriteLine("Start");
Console.WriteLine("Load Test Data");
using (var r = new StreamReader(#"C:\Production\test.json"))
{
string json = r.ReadToEnd();
testModel = JsonConvert.DeserializeObject<TestModel[]>(json);
}
GetTests();
Console.WriteLine("End");
Console.Read();
}
I feel like this should be populated when the Json file is read and put into the model.
As you said: You did not instantiate the arrays.
You could for example do it in the constructor, use the setters or simply do it inline (C# 6.0 required):
public class Conditions
{
public string[] Country { get; set; } = new string[length];
public int[] Grades { get; set; } = new int[length];
public string[] Disciplines { get; set; } = new string[length];
}
"length" is the length of the array. If you don't know the size, you might consider using a List<> or something like that.
Switching to List for each of the properties worked. I shall edit the code above with the correct answer, Thanks to #Thomas D. for pointing me in that direction

Return a List<SomeObject> without a certain property using Linq in c#?

I have an object containing different properties like the object below:
public class CompressedLogResponse
{
public string LoggerType { get; set; }
public int NumberOfRegisters { get; set; }
public int NewLogId { get; set; }
public DateTime LoggerAnnounceTime { get; set; }
public List<Log> Log{ get; set; }
}
How can I return a List of this objekt that does not include the List<Log> Log property?
Linq would be preffered
Thanks for any help that you can provide
You cannot just hide a property of a class (you declared it a as public)
Option 1:
Althought as Robson wrote you can set it null (thats not very reliable thaught cause nobody expects a class containing a property that is always null)
Option2:
If you consume the class on the same place use a anonymous type as Mez wrote, althought it sounds like you want to hide the Property from external usage. (I don't like the dynamic approach, the dynamic keyword was made for interop/DOM not for transporting anonymous types.)
Option3:
If you want a List of this type to be returned without the Log property, you have to create a new class (Inheritance is a good way to realize this):
public class CompressedLogResponseBase
{
public string LoggerType { get; set; }
public int NumberOfRegisters { get; set; }
public int NewLogId { get; set; }
public DateTime LoggerAnnounceTime { get; set; }
}
public class CompressedLogResponse : CompressedLogResponseBase
{
public List<Log> Log{ get; set; }
}
Now you can return a list of base items (that do not have a Log property at all)
public List<CompressedLogResponseBase> ReturnWithoutLog(IEnumerable<CompressedLogResponse> items)
{
return ((IEnumerable<CompressedLogResponseBase>)items).ToList();
}
If a IEnumerable as return type is suficient it becomes really easy
public IEnumerable<CompressedLogResponseBase> ReturnWithoutLog(IEnumerable<CompressedLogResponse> items)
{
return items
}
whith "does not include the List Log property" i guess you mean that the property "public List Log" will be blanked but still there, so you can just null that property out, because if you create an object that doesn't contain the "public List Log" property, than it will not be a "CompressedLogResponse" but will be another type.
List<CompressedLogResponse> listOne = new List<CompressedLogResponse>();
//....
//fill the listOne
//....
List<CompressedLogResponse> listWithoutListLog = (from item in listOne
select new CompressedLogResponse(
LoggerType = item.LoggerType,
NumberOfRegisters = item.NumberOfRegisters ,
NewLogId = item.NewLogId ,
LoggerAnnounceTime = item.LoggerAnnounceTime ,
Log= null)).ToList();
You can return an anonymous list of your original list like the following;
public static List<dynamic> Test() {
List<CompressedLogResponse> list = new List<CompressedLogResponse>();
var result = list.Select(x => new
{
x.LoggerAnnounceTime,
x.LoggerType,
x.NewLogId,
x.NumberOfRegisters
});
return result.ToList<dynamic>();
}
Take a look at the .Select(), and also the dynamic keyword.
Then to call it,
var x = Test();
foreach(dynamic o in x)
{
int NumberOfRegisters;
//You have 2 ways... either by
NumberOfRegisters = o.NumberOfRegisters;
// or reflection
NumberOfRegisters = o.GetType().GetProperty("NumberOfRegisters").GetValue(o, null);
}

C# nested class/struct visibility

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.

Categories

Resources