Initialize list with default values - c#

I want to have a class, that stores all "allowed languages" in a list. Code party should be able to modify the list. But on first usage, the list should be "initialized" with some default values.
I have the following class:
public class ApiLanguages
{
public static List<string> AllowedLanguages { get; set; }
public ApiLanguages()
{
AllowedLanguages.Add("de");
//AllowedLanguages.Add("en");
//AllowedLanguages.Add("es");
//AllowedLanguages.Add("fr");
//AllowedLanguages.Add("it");
}
}
When I access the class now in code with
foreach (var language in ApiLanguages.AllowedLanguages)
{
// do something here...
}
the ApiLanguages.AllowedLanguages is null. But I expect one entry ("de"). What I am doing wrong here?

public ApiLanguages() is an instance constructor. It runs only (and every time) when you create a new instance of ApiLanguages (via new ApiLanguages()). It's purpose is to initialize instance variables, not static ones. You usually shouldn't initialize static properties or fields in an instance constructor.
You need to use the static constructor to initialize the static list like this:
public class ApiLanguages
{
public static List<string> AllowedLanguages { get; set; }
static ApiLanguages()
{
AllowedLanguages = new List<string>();
AllowedLanguages.Add("de");
//...
}
}

You can make your constructor static as well, but I prefer lazy loading. By this you will not populate list again and again whenever object is created of ApiLanguages,
public class ApiLanguages
{
private static IEnumerable<string> _allowedLanguages;
public static IEnumerable<string> AllowedLanguages
{
get
{
return _allowedLangues ?? (_allowedLangues = new List<string>{ "EN", "AR"});
}
}
}

You should initialize AllowedLanguages with new instance of List<string> first. You can do it with initializers for auto-properties in c# 6.0 or in the static constructor for older versions of c#.
public class ApiLanguages
{
// c# 6.0 syntax
public static List<string> AllowedLanguages { get; set; } = new List<string>();
static ApiLanguages()
{
// c# < 6.0 (old style) syntax
AllowedLanguages = new List<string>();
}
public ApiLanguages()
{
AllowedLanguages.Add("de");
}
}
Also I'm sure that you no need to add new values to the list for each instance of ApiLanguages class then you should move AllowedLanguages.Add(...) to the static constructor too. And you can join object creation and initialization to a single line of code:
public static List<string> AllowedLanguages { get; set; } = new List<string>() { "de", "en", "ru" };

Related

Explicit interface implementation not working when passing into method with higher interface type

I have a class that contains a list of items (implement IHasItems). In a specific scenario, I want to hide these items by explicit implement IHiddenItems to return empty list.
But there is an existing method (PrintItems - in this case), the input parameter type is IHasItems. Consequently, the items can not be hidden in the method even if I cast the object to IHiddenItems.
The reason to try this approach is that I don't want to create a prototype of this object and set it empty in the prototype instance.
public interface IHasItems
{
IEnumerable<string> Items { get; }
}
public interface IHiddenItems : IHasItems
{
new IEnumerable<string> Items { get; }
}
public class Implementation : IHasItems, IHiddenItems
{
public Implementation()
{
Items = new List<string>()
{
"A","B","C"
};
}
public IEnumerable<string> Items { get; }
IEnumerable<string> IHiddenItems.Items { get; } = new List<string>(); // Empty
}
static class Program
{
static void Main()
{
Implementation derivedClass = new Implementation();
Console.WriteLine($"Implementation: {derivedClass.Items.Count()}");
Console.WriteLine($"IHasList: {((IHasItems)derivedClass).Items.Count()}");
Console.WriteLine($"IEmptyList: {((IHiddenItems)derivedClass).Items.Count()}");
PrintItems(((IHiddenItems)derivedClass));
Console.Read();
}
public static void PrintItems(IHasItems obj)
{
Console.WriteLine($"PrintItems method: {obj.Items.Count()}");
}
}
Result
Implementation: 3
IHasList: 3
IEmptyList: 0
PrintItems method: 3
Expected
Without modify PrintItems, it should display to console PrintItems method: 0

Call one method with parent class instead of two with childs

I have classes:
public class Throw
{
public double speed { get; set; }
public double accurency { get; set; }
}
public class FastThrow : Throw{}
public class LowThrow : Throw{}
Instead of having:
public static FastThrow SetFastThrow(List<object> args)
{
return new FastThrow
{
speed = (double)args[0],
accurency = (double)args[1]
};
}
public static LowThrow SetLowThrow(List<object> args)
{
return new LowThrow
{
speed = (double)args[0],
accurency = (double)args[1]
};
}
I want to have one with parent class:
public static Throw SetThrow(List<object> args)
{
return new Throw
{
speed = (double)args[0],
accurency = (double)args[1]
};
}
To declare list or some other generic interface with child class with instance of parent class. Then adding new elements to existing collection. I know that below example has compilation errors, but it should look like:
List<List<object>> firstList = new List<List<object>>();
public void Main()
{
IList<FastThrow> secondList = new List<Throw>();
foreach (var item in firstList)
{
secondList.Add(SetThrow(item));
}
}
I read about contravariance and do not know if this is possible.
You can't. Rahter than
To declare list or some other generic interface with child class with
instance of parent class.
you should
To declare list or some other generic interface with parent class with
instance of chidlren class.
The second way, as Anirban said, use generic classes, refactor your SetThrow method as following:
public static T SetThrow<T>(List<object> args) where T : Throw, new()
{
return new T
{
speed = (double)args[0],
accurency = (double)args[1]
};
}
So that you can use SetThrow method only to generate different kinds of classes as long as they are child classes. e.g:
IList<FastThrow> secondList = new List<FastThrow>();
foreach (var item in firstList)
{
secondList.Add(SetThrow<FastThrow>(item));
}
And generic classes are strong typed and elegant to use.

Pass list to another form

I have a class that has several lists. The name of this class is Trans .
I want use this lists in another forms but I'm not able to call it's lists.
When I make an object from the Trans class it's lists will reset.
How can I use this lists in all of forms of the project ?
class Trans
{
public static List<string> name_list = new List<string>();
public static List<string> family_list = new List<string>();
public static List<string> phoneno_list = new List<string>();
public List<string> name_Sec_list { set { name_list = value; } get { return name_list; } }
public List<string> family_Sec_list { set { name_list = value; } get { return name_list; } }
public List<string> phoneno_Sec_list { set { name_list = value; } get { return name_list; } }
}
And Form1
Trans data = new Trans();
data.name_Sec_list.Add(name.Text);
data.family_Sec_list.Add(name.Text);
data.phoneno_Sec_list.Add(name.Text);
When I'm on Form2 and wanna to use my lists I can't So I should make object from Trans class and this work will make list values null.
you could use a singleton pattern:
class Trans {
private static Trans instance;
private Trans() { }
public static Trans Instance() {
if (instance == null) {
instance = new Trans();
}
return instance;
}
...
}
use it in first form:
Trans trans = Trans.Instance();
trans.name_Sec_list ....
use it in second form:
Trans trans = Trans.Instance();
trans.name_Sec_list ....
As others have suggested, a quick solution could be to make the properties static. However, this will likely introduce new problems such as testability, and it violates clean code principles.
The Singleton approach is already better, since the you could potentially make it configurable to return a test object for unit tests. However, getting the Singleton requires a static method, which can again be called all over the place.
So, both, static properties and Singletons will increase the likelyness of Spaghetti code. That's because you have no control over who can access the data and who cannot.
You have not exactly specified how many forms you have, how they are opened etc. so I will need to make some assumptions.
The main method could look like this:
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
var data = new Trans();
var secondForm = new Form2 {Trans = data};
var mainForm = new Form1 {SubForm = secondForm, Trans = data };
Application.Run(mainForm);
}
And I have modified the Trans class so that it does not have static items any more. I also fixed that class, because IMHO it had a copy/paste problem. It's likely that you introduced all the _Sec_ stuff for testing purposes, so they can likely be removed (they return the same object, which doesn't solve any problem).
class Trans
{
public List<string> name_list = new List<string>();
public List<string> family_list = new List<string>();
public List<string> phoneno_list = new List<string>();
public List<string> name_Sec_list { set { name_list = value; } get { return name_list; } }
public List<string> family_Sec_list { set { family_list = value; } get { return family_list; } }
public List<string> phoneno_Sec_list { set { phoneno_list = value; } get { return phoneno_list; } }
}
What can you see here?
both, Form1 and Form2 have access to the data, so it solves your problem.
the Main() method has control over who gets which data. Everyone who needs that data gets the data.
Nobody else gets access to the data. While everyone could new up a Trans himself, that would just be empty.
Since there's nothing static any more, you can safely use new instances of Trans during unit tests without any side effects
The forms do not create their dependencies themselves. The dependency is now injected into the form. This makes it possible to replace it by a mock object with defined test behavior in a unit test. (Another question is whether you should test UIs in unit tests, but that's a different topic).
You have 3 static lists in your Trans class already, if you want to use them make other also static:
public class Trans
{
public static List<string> name_list = new List<string>();
public static List<string> family_list = new List<string>();
public static List<string> phoneno_list = new List<string>();
public static List<string> name_Sec_list = new List<string>();
public static List<string> family_Sec_list = new List<string>();
public static List<string> phoneno_Sec_list = new List<string>();
}
Then everywhere you want to use these lists you should access them like:
Trans.name_Sec_list.Add(name.Text);
Now you can use these lists in any form that you want.
Just use a static class
public static class Trans
{
public static List<string> name_list = new List<string>();
public static List<string> family_list = new List<string>();
public static List<string> phoneno_list = new List<string>();
}
Usage
Trans.name_list.Add(string);
I'd put the static class in a separate project so it can be referenced elsewhere if needed. But only if needed.

C# 6.0 to < 6.0

I need to convert the following code which is in C# 6.0 to a lower version which works in .NET framework 4.5.
public ImageCollection Strokes { get; } = new ImageCollection(); //C# 6.0
How do i convert this?
Tried the below code but had few issues in the application.
public ImageCollection Strokes
{ get { return new ImageCollection(); } } //< 6.0
Kindly help. Also is there any way to convert these? Often i get solutions in 6.0 which i have to downgrade.
Its not the same.
In the first example you have a property which will be instantiated through the constructor.
In the second example you return a new instance every time you access the property.
The correct refactor looks like this:
public ImageCollection Strokes
{
get; private set;
}
public constructor()
{
Strokes = new ImageCollection();
}
You are going to have to assign the property in your constructor.
Option 1 - A property with a private setter:
class Example
{
public ImageCollection Strokes { get; private set; }
public Example()
{
Strokes = new ImageCollection();
}
}
Option 2 - A property with a getter only, backed by a private readonly field:
class Example
{
public ImageCollection Strokes { get { return _strokes; } }
private readonly ImageCollection _strokes;
public Example()
{
_strokes = new ImageCollection();
}
}
Option 3 - Like option 2, but assigning the field inline instead of in the constructor:
class Example
{
public ImageCollection Strokes { get { return _strokes; } }
private readonly ImageCollection _strokes = new ImageCollection();
}
You could create a private field that the getter uses:
class MyClass
{
private ImageCollection _strokes = new ImageCollection();
public ImageCollection Strokes { get { return _strokes } }
}
Or you could initialize it in the constructor.
class MyClass
{
public ImageCollection Strokes { get; private set; }
public MyClass()
{
Strokes = new ImageCollection();
}
}
Just remember to initialize it in all constructors of the class, or at least have your other constructors call a constructor that does.
The problem with your solution is that it returns a new instance of ImageCollection each time get is called. This produces multiple that have nothing to do with each other. Changing one will not change the rest.
I dont know what issues you arr facing but change code like below
your code always creating the new object , but 6.0 one time initialization
Try
var imgCollection = new ImageCollection();
public ImageCollection Strokes
{ get { return imgCollection; } } //< 6.0

Passing a List to another class

I know some codes here are not clear. I'm still in the process of trying out things. I've got three questions, why does an error shows up when adding a string in my list? How do I pass the List in Class1 to my main class? And is my syntax correct in List passArr? Not sure if I should add parenthesis at the end of passArr.
class Class1
{
public static List<string> passArr
{
get;
set;
}
public static void passIt()
{
passArr.Add("A"); //Error: Object reference not set to an instance of an object
}
}
Main Class
class Program
{
static void Main(string[] args)
{
Class1.passIt();
List<string> passArr1 = Class1.passArr;
foreach (string s in passArr1)
{
Console.WriteLine(s);
}
Console.ReadLine();
}
}
You're never creating a list, so the passArr property (which needs renaming, by the way) always has a value of null. You need something like:
Class1.passArr = new List<string>();
at some point. Another alternative would be to make it a read-only property backed by a field with an initializer:
private static readonly List<string> passArr = new List<string>();
public static List<string> PassArr { get { return passArr; } }
(This complies with naming convention in terms of case, but it's still not a meaningful name, of course.)
Thanks to Jon Skeet and Sayse for the answers. It's all now clear to me, the real problem is I'm trying to add something in the list (using passIt method) without creating a new object for the list.
Here's my new code:
Main Class
class Program
{
static void Main(string[] args)
{
Class1 cs = new Class1();
cs.passIt();
foreach (string s in cs.passArr)
{
Console.WriteLine("Inside main: " + s);
}
Console.ReadLine();
}
}
Class1
class Class1
{
public List<string> passArr
{
get;
set;
}
public void passIt()
{
passArr = new List<string>();
passArr.Add("A");
}
}

Categories