How do I make an arraylist public - c#

In File1 I created a class with 3 strings. I created another class with a public arraylist. I want this arraylist to be dynamic and the object it contains are the class with the 3 strings.
I can access the members of the class in the file but not in a separate file.
file1
public class SensorCollection
{
public string ipAddress;
public string portNumber;
public string physicalLocation;
public DetectorCollection(string ipAddr, string portNum, string loc)
{
this.ipAddress = ipAddr;
this.portNumber = portNum;
this.physicalLocation = loc;
}
}
public class SensorCollectionArray
{
public System.Collections.ArrayList SensorArrayList;
}
...
System.Collections.ArrayList DetectorArrayList = new System.Collections.ArrayList();
...
DetectorArrayList.Add(new DetectorCollection(ipAddress, portNum, str));
So I can fill the array of classes but can't access it in a separate file.
File 2
AdvancedSettingsForm.SensorCollectionArray mainDetectorCollectionArray;
System.Collections.ArrayList arrList;

If you create a SensorCollectionArray like this:
SensorCollectionArray mySCA = new SensorCollectionArray();
Then you can access it's ArrayList like this (for example, to add an item):
mySCA.SensorArrayList.Add(mySensorCollection);
Note however, that in the code you've posted, you didn't include a constructor for the SensorCollectionArray, so the SensorArrayList will be null after instantiation. So you can either set it to a separately instantiated ArrayList, or you can create the ArrayList within your SensorCollectionArray class.
Final note: You might want to look into the generic List(of T) class if you want to create a strongly typed collection

Not entirely sure what're attempting to do, but I assume it's something like the below. Presumably, you're creating a collection of your sensors because you want to apply some rules of some kind before storing it to the collection.
"Is this a good sensor? It is? Add it to the collection!"
Otherwise, you could just use a
List<Sensor> mySensors;
and not really use a class that'll essentially doing the same things. Aside from that, like it's been mentioned there's not really a reason to use ArrayList. As Marc points out here, the most compelling reason to use ArrayList is if you're using .NET 1.1; otherwise, you should use the generic List collection and all the great things it does for you.
//Sensor.cs
public class Sensor
{
public string Ip{ get; set; }
public string Port{ get; set; }
public string PhysicalLocation{ get; set }
public Sensor(string ipAddr, string portNum, string loc)
{
Ip= ipAddr;
Port= portNum;
PhysicalLocation= loc;
}
}
//SensorCollection.cs
public class SensorCollection
{
private List<Sensor> sensors;
public Sensor this[int i]
{
get { return this.sensors[i]; }
set { this.sensors[i] = value; }
}
public IEnumerable<Sensor> Sensors
{
get{ return this.sensors; }
}
public SensorCollection()
{
sensors = new List<Sensor>();
}
public SensorCollection(string ip, string port, string location) : this()
{
this.sensors.Add(new Sensor(ip, port, location));
}
public SensorCollection(Sensor sensor) : this()
{
this.sensors.Add(sensor);
}
public void AddSensor(Sensor sensor)
{
//Determine whether or not to add it
this.sensors.Add(sensor);
}
public void RemoveSensor(Sensor sensor)
{
if (sensors.Contains(sensor))
sensors.Remove(sensor);
}
}
Edit
How do I access the ipaddress of each sensor in my dynamically created
list of classes?
var mySensors = new SensorCollection();
mySensors.AddSensor(new Sensor("1.1.1.1", "123", "Home"));
mySensors.AddSensor(new Sensor("9.9.9.9", "123", "Work"));
foreach(Sensor s in mySensors.Sensors)
Console.WriteLine(s.Ip);
I can not seem to access the members of the class in another file
Make sure they're in the same namespace, or that you include a "using" statement that includes the namespace of your classes you create.

Related

Can static values be read from a file?

I created a C# code for logging error codes.
I hardcoded the error codes into a class RecordId as static ints.
public class RecordId
{
public static int UnknownCommand = 100;
public static int SoftwareVersion = 101;
public static int WarningError = 110;
public static int AbortError = 111;
// etc...
}
Having static int means that I can do RecordId.SoftwareVersion anywhere in my code, I don't actually need to instantiate the class RecordId, which is very convenient, since I want to be able to log things from different parts of the code by calling a Log class that also doesn't need instantiation (it just appends a message to a file)
The logging function is also static, being something like
public class Logger
{
public static void LogExperiment(int key, string value)
{
// Append key and value to a hardcoded filename
}
}
Then from anywhere in my code I can do
Logger.LogExperiment(RecordId.SoftwareVersion, "1.0");
This will just append 101 1.0 in a log file
I don't need instances of the classes, so I can log anywhere from my code.
Now, as the code grows, I don't want to modify the code every time I add a new RecordId, so I want to have a JSON file where I load the values into the class.
I modified the RecordId class to look like:
public class RecordIdNew
{
public String UnknownCommand { get; set; }
public String SoftwareVersion { get; set; }
public String WarningError { get; set; }
public String AbortError { get; set; }
}
The problem I see now, is that in order to populate this values from the JSON file I have to instantiate the class RecordId, whereas before I was using the values as static ints, and therefore I could call RecordId.SoftwareVersion
The question (which might be a bit open) is: Is there a way I can keep RecordId not instantiated, but access values that come from a JSON file.
Or if not possible, is there another structure that would allow me to do that?
You are looking for static constructor, i.e.
// Let's have class being static if you don't want to create instances
public static class RecordId
{
// To be on the safer side of the road, let's have readonly fields:
// once set in the static constructor they can't be changed
public static readonly int UnknownCommand;
public static readonly int SoftwareVersion;
public static readonly int WarningError;
public static readonly int AbortError;
// Static constructor, it will be called before the first read of any field
static RecordId() {
//TODO: put your logic here: read the file and assign values to the fields
}
}
Edit:
Please, have a look at the your current design, maybe you are looking for {Key, Value} pairs? E.g. Key == 100, Value == "UnknownCommand" etc.
If it's your case, try using Dictionary:
public static class RecordId {
private static readonly Dictionary<int, string> s_Names = new();
public IReadOnlyDictionary<int, string> Names => s_Names;
static RecordId() {
//TODO: Your logic here (fill in s_Names)
}
}
usage:
int code = 100;
if (RecordId.Names.TryGetValue(code, out var name))
Console.WriteLine($"{code} is {name}");
else
Console.WriteLine("Unknown code");
Assuming you can perfectly match up the static C# properties or fields to the values in the JSON, you can use ModuleInitializerAttribute to set the static properties.
public static class RecordId
{
public static int UnknownCommand { get; private set; }
public static int SoftwareVersion { get; private set; }
public static int WarningError { get; private set; }
public static int AbortError { get; private set; }
// etc...
[ModuleInitializer]
public static void Init()
{
// code to read JSON
// loop over JSON fields, matching them to
// above fields, setting their values...
}
}
This gives you a way to set the values at runtime, once, when the module loads (modules are groups of logical code in an assembly (reference)).
Module initializers are guaranteed to be run before any other access to the module; so if you reference, say, UnknownCommand anywhere, you will get the value that was read from the JSON. In fact, as Dmitry notes in the comments, the module init code is guaranteed to run period, even if no other code in the module is accessed at all. This could be a drawback if the code is slow or buggy, but useful in cases such as yours.
This does not give you a way to dynamically create the properties; that would require either code generation prior to compilation or access to the values at runtime via some sort of "Get" method coupled with a static dictionary.
Here's an article on the subject, and here's the original proposal on GitHub.

Lists that implement an Interface, and passing a reference to that list

I have several different lists of objects, ie
List<Character> characters;
// ...
and some of those lists are of objects that implement the same interface:
public interface IDebugPrints
// ...
public class Character : IDebugPrints
// ...
I have a class where I would like to store a reference to a list (passed to it in its constructor) that implements IDebugPrints, ie
List<IDebugPrints> inList
So that later I can iterate through that list (in this case to print out debug information about the current entries in the original List).
I can't figure out how to do this. If I pass the List as IEnumerable, it makes a copy of the original list, which dosent work for me since objects are added and removed from the original list after that copy.
Any help is appreciated. I have a feeling this isnt possible based on a few other questions here on SO, but would appreciate confirmation.
EDIT:
Here is a bit more pseudo code:
public interface IDebugPrints
// ...
public class Character : IDebugPrints
// ...
public class StoreList
{
private List<IDebugPrints> internalList;
public StoreList( List<IDebugPrints> inList )
{
internalList = inList;
}
}
// The I have the various lists, for example
List<Character> characters;
// ...
// And I want to pass that list
StoreList sl = new StoreList( characters );
This last line gives compile errors:
Cannot convert from System.Collections.Generic.List<Character> to Systems.Collections.Generic.List<IDebugPrints>
Pass List<Character> characters as a IEnumerable<IDebugPrint>. This works beginning with C# 4.
Make internalList and inList typed as IEnumerable<IDebugPrint>.
Reference types are never copied in C# (except if explicitly implemented and requested by the programmer). .NET has no general way to copy an arbitrary reference type instance.
This means that your variables of type IEnumerable<IDebugPrint> will refer to the existing modifiable list.
This compiles:
using Microsoft.VisualStudio.TestPlatform.UnitTestFramework;
using System.Collections.Generic;
public interface IDebugPrints
{
}
public class Character : IDebugPrints
{
}
public class StoreList
{
private List<IDebugPrints> internalList;
public StoreList(List<IDebugPrints> inList)
{
internalList = inList;
}
}
[TestClass]
public class Test1
{
[TestMethod]
public void MyTest()
{
var characters = new List<IDebugPrints>();
characters.Add(new Character());
var sl = new StoreList(characters);
}
}
It isn't possible to cast a List<x> to a List<y> directly, unless you're using casting methods like:
List<x> listX = listY.Cast<x>();
I would pass the List<Character> as an IList to the StoreList.
With the .OfType<>() extension, you can iterate the childs of the type given.
This way, the list isn't copied.
This way your StoreList can iterate it, not depending on the types you passed, as long the items are inherited from IDebugPrint, the ShowAllInfo will show the Info.
Here's an example:
public interface IDebugPrints
{
string Info { get; set; }
void ShowInfo();
}
public class Character : IDebugPrints
{
public string Info {get;set;}
public void ShowInfo()
{
Console.WriteLine(Info);
}
}
public class StoreList
{
private IList internalList;
public StoreList(IList inList)
{
internalList = inList;
}
public void ShowAllInfo()
{
// I love the OfType<>() extension, it only returns the items of type IDebugPrints.
foreach (var item in internalList.OfType<IDebugPrints>())
item.ShowInfo();
}
}
class Program
{
static void Main(string[] args)
{
List<Character> characters = new List<Character>();
characters.Add(new Character { Info = "Character 1" });
characters.Add(new Character { Info = "Character 2" });
// And I want to pass that list
StoreList sl = new StoreList(characters);
sl.ShowAllInfo();
Console.ReadKey();
}
}

Writing out properties specific to a Derived Class

I need to determine which object my code is working with at a certain point and write out only the properties specific to that class. I cannot figure out how to do it. I was told I can do it, but I cannot figure it out. Can someone please show me how to determine which object I am working with and write the properties specific to that class only?
I've looked at other questions asked, but am not smart enough to make it fit my example.
Below, I've re-created an example of the code I am working with. I can see all the code, but I am allowed to only work in one method (for this example called "MethodIAmWorkingIn"). Only modifications I am allowed to make are in that method.
public class Program
{
static void Main(string[] args)
{
TestDetailsAndResultsContainer container = new TestDetailsAndResultsContainer();
DerivedClass1 derivedClass1 = new DerivedClass1();
derivedClass1.DerivedClass1Prop1 = "DerivedClass1Prop1";
derivedClass1.DerivedClass1Prop2 = "DerivedClass1Prop2";
DerivedClass2 derivedClass2 = new DerivedClass2();
derivedClass2.DerivedClass2Prop1 = "DerivedClass2Prop1";
derivedClass2.DerivedClass2Prop2 = "DerivedClass2Prop2";
container.TestDetails.Add(derivedClass1);
container.TestDetails.Add(derivedClass2);
TestResult testResult = new TestResult();
testResult.TestResultProp1 = "TestResultProp1";
testResult.TestResultProp2 = "TestResultProp2";
container.Data.Add(testResult);
Program p = new Program();
p.MethodIAmWorkingIn(container);
}
private void MethodIAmWorkingIn(TestDetailsAndResultsContainer container)
{
// I need to see if the container variable holds a DerivedClass1 or DerivedClass2 object.
foreach (var result in container.TestDetails)
{
var classINeedToDetermine = container.TestDetails.FirstOrDefault(m => m.TestDetailsProp1 == result.TestDetailsProp1);
if (classINeedToDetermine is DerivedClass1)
{
classINeedToDetermine = result as DerivedClass1;
}
else if (classINeedToDetermine is DerivedClass2)
{
classINeedToDetermine = result as DerivedClass2;
}
// Now I need to use the classINeedToDetermine object and write its specific properties.
// ???????????????????? I am stuck at this point ??????????????????
// I need to write one or the other below. Can this be done?
// If it is DerivedClass1, I need to write out those properties only.
Console.WriteLine(classINeedToDetermine.DerivedClass1Prop1);
Console.WriteLine(classINeedToDetermine.DerivedClass1Prop2);
// OR
// If it is DerivedClass2, I need to write out those properties only.
Console.WriteLine(classINeedToDetermine.DerivedClass2Prop1);
Console.WriteLine(classINeedToDetermine.DerivedClass2Prop2);
}
}
}
public class TestDetailsAndResultsContainer
{
public TestDetailsAndResultsContainer()
{
this.Data = new List<TestResult>();
this.TestDetails = new List<TestDetails>();
}
public List<TestDetails> TestDetails { get; set; }
public List<TestResult> Data { get; set; }
}
public abstract class TestDetails
{
public string TestDetailsProp1 { get; set; }
public string TestDetailsProp2 { get; set; }
}
public class TestResult
{
public string TestResultProp1 { get; set; }
public string TestResultProp2 { get; set; }
}
public class DerivedClass1 : TestDetails
{
public string DerivedClass1Prop1 { get; set; }
public string DerivedClass1Prop2 { get; set; }
}
public class DerivedClass2 : TestDetails
{
public string DerivedClass2Prop1 { get; set; }
public string DerivedClass2Prop2 { get; set; }
}
The as keyword does not do what you think it does.
Your classINeedToDetermine is a variable of type TestDetails. You can assign a subclass instance to it, but you still cannot access that subclasses specific properties via that variable.
You just need some scope:
if (classINeedToDetermine is DerivedClass1)
{
var derived1 = (DerivedClass1)result;
Console.WriteLine(derived1.DerivedClass1Prop1);
// etc
}
else if (classINeedToDetermine is DerivedClass2)
{
var derived2 = (DerivedClass2)result;
Console.WriteLine(derived2.DerivedClass2Prop1);
// etc
}
This kind of thing is not fun to maintain though.
Another way of doing it would be to use polymorphism: Your TestDetails class could define an abstract method called PrintProperties, and all your subclasses could implement it.
Then you just have to call PrintProperties on every object, without worrying about which subclass they are.
I'm not completely sure on what objects mean what here, but it should be something like this:
foreach(var v in result.GetType().GetProperties())
{
if(v.DeclaringType == result.GetType())
{
Console.WriteLine(v.GetValue(result));
}
}
Again, I wasn't totally clear on your usage of classINeedToDetermine versus result, but you can change those as you see so fit. I chose result as my example since classINeedToDetermine was null by that part of your code.
And by the way, this section of your code is redundant. It should be removed for clarity and efficiency.
if (classINeedToDetermine is DerivedClass1)
{
classINeedToDetermine = result as DerivedClass1;
}
else if (classINeedToDetermine is DerivedClass2)
{
classINeedToDetermine = result as DerivedClass2;
}
Edit:
On the other hand, if performance is more important to you than being scalable (read: if you know or have control over all the classes you'll be dealing with), you could use this is section to do something less, I hate to use this word for this, "generic."
if (classINeedToDetermine is DerivedClass1)
{
var typed = (DerivedClass1)result;
Console.WriteLine(typed.DerivedClass1Prop1);
Console.WriteLine(typed.DerivedClass1Prop2);
}
else if (classINeedToDetermine is DerivedClass2)
{
var typed = (DerivedClass2)result;
Console.WriteLine(typed.DerivedClass2Prop1);
Console.WriteLine(typed.DerivedClass2Prop2);
}
You can use Type.GetProperties to get all Properties for your class. Then you need to get the MethodInfo for the Get method via GetMethod.
Once you have the MethodInfo you can call Invoke, passing in your Derived Class. You can write then write the result to the Console.

list property inside of a struct

How do I write a property for a list inside of a struct?
my code:
public struct Config
{
List<int> ipAddress = new List<int>();
}
If all you want is to create an auto-property (which will default to null for reference types and cannot be initialized) you can do as #scartag suggests.
public struct Config
{
// will default to null
List<int> ipAddress {get; set;}
}
However, if you're trying to do what's in your code and initialize it to an actual reference, you will run into issues because you can't initialize fields in a struct. They can only have their defaults. To make matters even worse, you can't override a default constructor to do this for you.
Generally speaking, struct tends to be best for small, preferably immutable types. Is there a reason you don't want to just use class for this?
Now, if you did want to create a struct with an "initialized" field, you can fool it with some lazy logic:
public struct Config
{
private List<int> _ipAddress;
private bool _isAssigned;
public List<int>
{
get
{
if (!_isAssigned)
_ipAddress = new List<int>;
return _ipAddress;
}
set
{
_ipAddress = value;
_isAssigned = true;
}
}
}
But really, at this rate it's better to use a class since you can initialize fields, or override the default constructor:
public class Config
{
public List<int> ipAddress {get; set;}
public Config()
{
ipAddress = new List<int>();
}
}
And again, as Andrew mentioned in the comments, I strongly suggest looking at MSDN guidance on choosing between struct and class
See below.
public struct Config
{
List<int> ipAddress { get; set; }
}
Or if you prefer not to use the automatic get/set
public List<int> ipAddress
{
get
{
return ipAddress?? new List<int>();
}
set
{
ipAddress = value;
}
}

How do I get the value of the used parameters in a constructor (C#)

I've got a question about getting the values from a constructor in a generic way.
namespace myTestNamespace
{
Public Class myTestClass()
{
Public myTestClass(int myInt,bool myBool, double myDouble)
{
//do / set something
}
Public myTestClass(int myInt,bool myBool)
{
//do / set something
}
}
}
Using (what you need);
Using myTestNamespace;
namespace MyIWannaLookForTheParametersName
{
Public Class MyLookUpClass()
{
Public void DoSomething()
{
List<object> myList = new List<object>();
myTestClass _ myTestClass = new myTestClass(1,true,2.5);
object mySaveObject = myTestClass;
mylist.Add(mySaveObject);
//how do I get the info from the right constructor
//(I used the one with 3 parameters_
//what was the value of myInt, myBool and myDouble
//how can I make it generic enough, so it will work with other classes with
// different constructors ass well?
}
}
}
Questions about intent aside, there's no generic way for you to do this. Information about what methods have been called and what values were supplied is not saved automatically. You are, of course, perfectly able to keep track of these things yourself, but you would have to write each class to do this explicitly.
Doing this in a generic way is asking for trouble. What if I did this?
public class Foo
{
public string Name { get; set; }
}
public class Bar
{
public Bar(Foo foo)
{
// ...
}
}
Then suppose I called it in this way:
Foo f = new Foo();
f.Name = "Jim";
Bar b = new Bar(f);
f.Name = "Bob";
Now, if such a generic system existed, what would be the value of foo for the Bar constructor? Either it reports "Bob" (which is what the value for Name is on the instance of Foo that was supplied), or it reports "Jim", meaning that the runtime or library would essentially have to be smart enough to make a deep copy of the object so that the state is not changed.
The bottom line is this: if you need access to the parameters passed to the constructor (or any other function), you'll have to store them somewhere explicitly.
You can't get thevalues from the constructor. You need to first place them in a property or a field within your class. The example you provided is a poor use of generics. You wouldbe better off placing the constructor values into properties and creating an interface with those properties.
I got what I needed with this method:
private static ParameterSettings[] GetListOfParametersFromIndicator(object indicatorClass, int loopId, myEnums.ParaOrResult paraOrResult)
{
return (from prop in indicatorClass.GetType().GetProperties()
let loopID = loopId
let Indicator = indicatorClass.GetType().Name
let value = (object)prop.GetValue(indicatorClass, null)
where prop.Name.Contains("_Constr_")
select new ParameterSettings { ParaOrResult=paraOrResult, LoopID= loopId, Indicator= Indicator, ParaName= prop.Name, Value= value }).ToArray();
}
where ParameterSettings is:
public struct ParameterSettings
{
public myEnums.ParaOrResult ParaOrResult { get; set; }
public int LoopID { get; set; }
public string Indicator { get; set; }
public string ParaName { get; set; }
public object Value { get; set; }
}
This info is ok for me. Thanks for the replies.
Regards,
Matthijs

Categories

Resources