Passing a List to another class - c#

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

Related

Can't access class method in a seperate method c#, the name item1 does not exist in the current context

Trying to use a class method, with an instance of that class in a separate method. Used method RandomItem() to build instance of class Item. Using ViewItem() to display the item, it says:
"The name 'item1' does not exist in this context"
This is my code:
class Program
{
public class Item
{
public string part1;
public Item(string _part1)
{
part1 = _part1;
}
public void PrintItem()
{
Console.WriteLine(part1);
}
}
public static void Main()
{
RandomItem();
ViewItem();
}
public static void RandomItem() {
string randomPart1 ="";
Item item1 = new Item(randomPart1);
}
public static void ViewItem() {
item1.PrintItem(); //this is where the error is "The name 'item1' does not exist in the current context
}
}
}
Kind of new to c#, just not sure why I can't access item1.PrintItem(), or if I'm even allowed to do this. Any help would be much appreciated.
If a variable is local, you need to return it so the caller can access it. Then you need to pass it as an argument for another method to access it.
public static void Main()
{
var item = RandomItem(); //Retrieve item
ViewItem(item); //Then pass it in
}
public static Item RandomItem() {
string randomPart1 ="";
Item item1 = new Item(randomPart1);
return item1; //Return the item to Main
}
public static void ViewItem(Item item1) { //Accept item as argument from Main
item1.PrintItem();
}
There are other options-- for example, you could use a static variable-- but this is the most common way to do it.
You need to declare "item1" outsite of your "RandomItem()" method as a member of your "Program" class.
On a console App the entry point is a static method. So everything you declare in your "Program" class must be static.
class Program
{
public static Item item1; // the static field that contains the instance of your "Item"
public class Item
{
public string part1;
public Item(string _part1)
{
part1 = _part1;
}
public void PrintItem()
{
Console.WriteLine(part1);
}
}
public static void Main()
{
RandomItem();
ViewItem();
}
public static void RandomItem() {
string randomPart1 ="";
item1 = new Item(randomPart1);
}
public static void ViewItem() {
item1.PrintItem();
}
}

public List<string> filled in one function becomes empty outside the function

I have class A in one file
public class A
{
public List<string> details;
public void fillList()
{
details = new List<string>();
details.Add("abc");
details.Add("xyz");}
}
public string[] convertToArray()
{
File.AppendAllText(path,"print list content \n"); /* this is getting printed */
File.AppendAllLines(path, details.ToArray()); /* no contents are getting printed here */
return details.ToArray();
}
}
I'm not able to access this list content outside this function.outside this function list is becoming empty.
I tried using static keyword as well.
Please suggest me solution to access this list outside.
I'm facing this issue only in windows 10.
This is happening for all types not only for List.
try this - new up the list in the constructor to avoid a null ref exception:
public class A
{
public List<string> details;
public A()
{
details = new List<string>();
}
public void fillList()
{
details.Add("abc");
details.Add("xyz");}
}
}

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.

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

Can't access the class I just created

I hope this is a simple question. I'm building a simple console application in C#. I have a class:
using System;
using Filter;
public class Params
{
public string key;
public bool distinct;
public List<string> fields;
public string filter;
public int limit;
public int skip;
public bool total;
public List<Tuple<string, GroupType>> group;
public List<Tuple<string, OrderType>> order;
public Params()
{
key = "";
distinct = false;
fields = new List<string>();
filter = "";
group = new List<Tuple<string, GroupType>>();
limit = 0;
order = new List<Tuple<string, OrderType>>();
skip = 0;
total = false;
}
public void AddGroup(string field, GroupType type)
{
group.Add(new Tuple<string, GroupType>(field, type));
}
public void AddOrder(string field, OrderType type)
{
order.Add(new Tuple<string, OrderType>(field, type));
}
}
My program .cs class is:
namespace csharpExample
{
class Program
{
public static void Main(string[] args)
{
Params p = new Params();
Console.WriteLine("Test");
}
}
}
I want to use Params in my program.cs class where Main() is called. I thought I could simply use Params like above. I've also tried to do a using Params; both of these are errors in VS since it can't find the directive. I've also tried adding my own namespace: namespace MyNameSpace; around my Params class. When I do this I still am unable to do a using MyNameSpace; statement as it can't find it.
I just want to extract out a bunch of functions into a class that I can reuse. How do i call this class once it's created?
-Thanks
Thanks for the help.
If you want to access the Params object in the Main function, just add Params p = new Params (); to the Main function at the top.
Most likely your problem is that Main is static, meaning that it can't access other things that aren't static which are outside of it. If you declared Params in the Program class, unless you made it static, it can't be accessed in Main.
Are you talking about calling the constructor or the properties you are setting? You can set the class at the top of your base class and then call the instance of it. But since it is a static class you should probably use a helper method in the main.
namespace Example
{
public class Program
{
Params p = new Params();
string writefromParams() // I exist just to give the string back from params with a nonstatic method
{
return p.key;
}
static void Main(string[] args)
{
Program p2 = new Program(); // set up a new instance of this very class
Console.WriteLine(p2.writefromParams()); // get non static method from class
Console.ReadLine();
}
}
}

Categories