Pass list to another form - c#

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.

Related

How can I instantiate a class with a method (if possible) in c#?

Say you had some sort of console-application game, and inside the game you create an object which would have it's own class. How would you make an instance of that class with something like a method or function while the game might still be running.
I've looked all over the internet and haven't found anything after weeks. Normally, I would just create an array for the class and add new instances to it like so.
class MyClass
{
//fields and methods
}
class Program
{
static void Main(string[] args)
{
MyClass[] myClasses = new MyClass[16];
myClasses.SetValue(new MyClass(), 0);
}
}
But this feels clunky and inefficient. I hope I figure this out soon.
There are many ways to do this. The most common and accepted way may be the FactoryPattern.
Create your factory:
public static class MyClassFactory
{
public static MyClass CreateNew() {
return new MyClass();
}
public static MyClass[] CreateRange(int amount) {
var myArr = new MyClass[amount];
for (int i = 0; i < amount; i++)
{
myArr[i] = new MyClass();
}
return myArr;
}
}
Then simply call it in your code:
class Program
{
static void Main(string[] args)
{
MyClass[] myClasses = MyClassFactory.CreateRange(16);
}
}
Are you trying to do this:
var myClasses = new MyClass[16];
myClasses[0] = new MyClass();

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.

Initialize list with default values

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" };

Is my builder design pattern thread-safe?

Coming from a Java background, I have to implement something in C#. The class is a domain object which is composed of multiple other domain objects. I don't like to have a constructor with 10 fields, so I thought of using the builder design pattern! Here is what I came up with:
public class MyDomainObject
{
public DomainObject1 Obj1 { get; private set; }
public DomainObject2 Obj2 { get; private set; }
public DomainObject3 Obj3 { get; private set; }
...
public class DomainObjectBuilder
{
private MyDomainObject _domainObj = new MyDomainObject();
public DomainObjectBuilder(DomainObject1 obj1)
{
_domainObj.Obj1 = obj1;
}
public DomainObjectBuilder withDomainObject2(DomainObject2 obj2)
{
_domainObj.Obj2 = obj2;
return this;
}
.....
public MyDomainObject Build()
{
// Construct and Return the MyDomainObject
}
}
}
Now is this implementation thread safe? When I instantiate my domain object the following way:
var myDomainObject = new DomainObjectBuilder(obj1)
.withDomainObject2(obj2)
.withDomainObject3(obj3).build();
What happens if the calls between withDomainObject2 and withDomainObject3 is handled by different threads?
I haven't come across any code that splits a builder on multiple threads. The simple answer given your requirements is simply (no it is not thread safe).
Consider this example using your MyDomainObject class:
private MyDomainObject _myObj;
void Main(string[] args)
{
DomainObject1 obj1 = new DomainObject1();
_myObj = new MyDomainObject(obj1);
Thread oThread1 = new Thread(ThreadProc1);
oThread1.Start();
Thread oThread2 = new Thread(ThreadProc2);
oThread2.Start();
MyDomainObject myObjFinal = _myObj.Build();
DomainObject2 obj2 = myObjFinal.Obj2; //No guarantee that Obj2 is set or initialized
DomainObject3 obj3 = myObjFinal.Obj3; //No guarantee that Obj3 is set or initialized
}
void ThreadProc1()
{
DomainObject2 obj2 = new DomainObject2();
MyDomainObject myObjModified = _myObj.withDomainObject2(obj2);
DomainObject3 objNew = _myObj.Obj3; //No guarantee that Obj3 is set or initialized
}
void ThreadProc2()
{
DomainObject3 obj3 = new DomainObject3();
MyDomainObject myObjModified = _myObj.withDomainObject3(obj3);
DomainObject2 objNew = _myObj.Obj2; //No guarantee that Obj2 is set or initialized
}
As you can see there is no guarantee that any of the objects is initialized or set when called after Build() in the main thread. The same applies when trying to access an object that is initialized in a different thread.
you don't need a constructor wit too many things.... the thing that you may not call some of these method, mean some of them are optional, i see that also i java, but here after some reversion of .NET framework, you can do it more simple... like this:
A a = new A(Required properties){
Name="x",
Family="Y",
OpetionalProperty3 = "z",
.......
};
and if you do not have any thing required, you can remove the parentheses at all( when you define optional properties).
A a = new A{
Name="x",
Family="Y",
OpetionalProperty3 = "z",
.......
};
And about your case and thread handeling, check out the 'volatile' syntax for variables - it ensure last value is in the field on every thread call

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