Multidimensional mixed array vs static classes vs anything else? - c#

I am trying to find the right structure to store some global variables. I basically have 2 set of similar variables grouped under Option A/B. The choice between A and B set is done from the app.config. The data have the following structure:
[OptionA][VAR1] = "myValue1OptionA"
[OptionA][VAR2] = {'a','b','c'}
[OptionA][VAR3] = 3
[OptionB][VAR1] = "myValue1OptionB"
[OptionB][VAR2] = {'a','b','c','d','e'}
[OptionB][VAR3] = 120
I can use a dictionary with a tuple as index but it is a bit heavy in term of casting when using the variables:
private static GlobalVar<Tuple<string, string>, var> instances =
new Dictionary<Tuple<string, string>, var>(){
{Tuple.Create("OptionA","VAR1"), "myValue1OptionA"},
{Tuple.Create("OptionA","VAR2"), {'a','b','c'}},
{Tuple.Create("OptionA","VAR3"), 3},
{Tuple.Create("OptionB","VAR1"), "myValue1OptionB"},
{Tuple.Create("OptionB","VAR2"), {'a','b','c','d','e'}},
{Tuple.Create("OptionB","VAR3"), 120},
};
I thought of 2 statics classes but retrieving the values and casting is also a bit cumbersome.
static class GlobalVarOptionA
{
static string VAR1 = "myValue1OptionA";
static char[] VAR2 = {'a','b','c'};
static int VAR3 = 3;
}
static class GlobalVarOptionB
{
static string VAR1 = "myValue1OptionB";
static char[] VAR2 = {'a','b','c','d','e'};
static int VAR3 = 120;
}
Usage should be something like:
Type t = Type.GetType("GlobalVarOptionB");
var pinfo = t.GetProperties(BindingFlags.Static | BindingFlags.Public);
Any help/advice will be appreciated.

If the choice between A and B comes form the app.config file, this means it is done once at startup of your program.
So you should create/initialize just one of these structures in memory after the app.config is read.
Because it is structured data (as opposed to a string/string list) I'd use a static class as you did with static class GlobalVarOption

For me better approach will be one static class with properties where you can internally check which option to return
or use singleton pattern
class GlobalVariables
{
public static GlobalVariables Instance = new GlobalVariables();
public readonly string VAR1;
public readonly char[] VAR2;
public readonly int VAR3;
private GlobalVariables()
{
// Set values based on the App.config options
}
}
Using
GlobalVariables.Instance.VAR1

Related

Static List Showing as Null [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 1 year ago.
Improve this question
I have a static class called Constants.
public static class Constants
{
public static string sampleString= "";
public static List<int> sampleList= new List<int> {1,2,3};
}
If I call my static list outside:
Constants.sampleList it gives me a null exception but Constants.sampleString can be called with no problem.
Am I missing something here?
Not sure if this is the same case as ours but we have a class that access the key from the config
string sampleString = WebConfigurationManager.AppSettings["SampleString"]
Sample string was deleted from our web.config due to some merging issues. Error for null pointer happens when you access any of the variables in the class bellow the variable.
Adding the key in the config fixed the issue.
When I run this code:
void Main()
{
Console.WriteLine(Constants.sampleList.Contains(1));
}
public static class Constants
{
public static string sampleString= "";
public static List<int> sampleList= new List<int> {1,2,3};
}
I get True on the Console. You need to provide the code which demonstrates the issue you're facing.
If you add readonly keyword to your method. The method can only be instantiated inside constructor or at the property declaration phase.
public static readonly List<int> sampleList= new List<int> {1,2,3};
If you ever try to reinitialize or make new assignment to sampleList, C# compiler will give you compiler error.
Yet better to use Property
public static readonly List<int> SampleList {get; set;} = new List<int> {1,2,3};
There are no miracles, and if sampleList is null (and you have exception thrown) then you asign null to it somewhere.
Try not to expose public fields which makes Constants vulnerable:
public static class Constants
{
public static string sampleString = "";
public static List<int> sampleList = new List<int> {1,2,3};
}
...
Constants.sampleList = null; // We can easly assign null
...
Constants.sampleList.Add(123); // <- And have an unxpected exception
But either turn them into properties:
public static class Constants
{
private static string s_SampleString = "";
private static List<int> s_SampleList = new List<int> {1,2,3};
public static string sampleString {
get {return s_SampleString;}
set {s_SampleString = value ?? "";}
}
public static List<int> sampleList {
get {return s_SampleList;}
// I doubt you actually want set here
set {s_SampleList = value ?? new List<int>();}
}
}
Or, at least, mark the field(s) as readonly (you can assign them once only):
public static class Constants
{
private static string s_SampleString = "";
public static string sampleString {
get {return s_SampleString;}
set {s_SampleString = value ?? "";}
}
// Manipulate with me, but not reassign
public static readonly List<int> sampleList = new List<int> {1,2,3};
}
In either case you still can manipulate with the list:
Constants.sampleList.Add(4);
Constants.sampleList.RemoveAt(0);
But you are protected from assigning null to the list: either empty list will be assigned (code with property) or you'll have compile time error (code with readonly)
In my case, I was defining a private static readonly Dictionary<byte, string> inside a struct to hold predefined constants. This normally would work fine, however I also had defined a MinValue within my struct to represent the minimum value of a piece of data. When done this way the static dictionary was uninitialized unless defined above the static MinValue property. I'm probably asking a little too much of the compiler and should restructure it instead.
It was hard to diagnose in a large struct as I didn't expect that behavior with C#. Example to reproduce:
public struct MyStruct
{
public string Str;
public static readonly MyStruct MinValue = new MyStruct(0);
public MyStruct(byte val)
{
Str = _predefinedValues[val]; // null reference exception
}
private static readonly Dictionary<byte, string> _predefinedValues = new Dictionary<byte, string>()
{
{0x00, "test 1"},
{0x01, "test 2"},
{0x02, "test 3"},
};
}
The solution here is twofold:
to not call any constructors on the struct and explicitly set each field without accessing _predefinedValues list.
Alternatively, moving the list up above the MinValue field declaration actually does fix it as well (strange right?)
I suspect something weird happens on the stack when trying to allocate this and it's probably a weird thing to do.

initializing of constant variable using method (C#)

Is it possible to initializing value of a constant value using method of another class
namespace ConsoleApplication1
{
class Program
{
const int gravit = haha.habc();//something like this
static void Main(string[] args)
{
some codes.....
}
public class haha
{
int gar = 1;
public int habc()
{
int sa = 1;
return sa;
}
}
}
}
For example like the codes above(FYI with this code I am getting Expression being assigned to ... must be constant), if not is there other method to do something similar to this.
No, that's not possible, you could use readonly field instead because constant values should be known at compile-time:
private static readonly int gravit = haha.habc();//something like this
NOTE: the habc method should be static if you want to call it that way.
Constants are values which should be known at compile time and do not change. So the ReadOnly is the option you should go with.
private readonly int gravit = haha.habc();

Pass a variable from one file to another c#

I have two .cs files (Hex2Bin.cs and Program.cs) and I want to pass the variable end_addr from Program.cs to Hex2Bin.cs
My code in Program.cs:
class Program
{
enum to_exit {
exit_ok = 0,
exit_invalid_args,
exit_to_few_args,
exit_invalid_input_file,
exit_invalid_args_file,
exit_permission_denied,
exit_unexpected_eof
};
// class value holders
static String args_file_name = "";
static String in_u1_name = "";
static String in_u22_name = "";
static String out_name = "";
static short end_addr = 0x0000; // 4-digit Hexadecimal end address
static Byte[] version_code = { 0, 0, 0, 0 }; // 3 bytes version, 1 for extra info
}
Is there anyway I could do this? I know how to do it in c, but I'm very new to c#. Thanks.
C# doesn't work like C with respect to static variables. You can make the variable end_addr available outside the Program class by making it a public field. By default, fields are private.
public static end_addr = 0x0000;
And then it can be accessed like so:
var x = Program.end_addr;
However, I would recommend that you spend a little more time familiarizing yourself with C# idioms and conventions. It seems like your still thinking about C# in terms of C, and they are very different.
if you declare the variable like this:
public static short end_addr = 0x0000;
then from another class you can use it like this:
Program.end_addr
but don't do this, is not object oriented!
if your class Hex2Bin is used/invoked by the Main method of Program class, you should be able to pass your variables as input parameters of the methods you call or set them as properties of the classes/objects you use...
It's enough to mark end_addr as public like so
public static short end_addr = 0x0000;
Then you can access it from anywhere like this
Program.end_addr
It's a better practice though to use properties rather than fields for exposing data.
// Property
public static short end_addr { get; private set; }
// Constructor
public Program()
{
// Initialize property value.
end_addr = 0x0000;
}
You're talking about 'files' but what you really want to do is to pass data from your program's entry point (Program.cs) to a an object of a class (or method of static class) that will process the data, am I right?
If so, this should be pretty simple. You either have to modify your Program.cs and create an instance of the class (the one from Hex2Bin.cs) like this
...
Hex2Bin hex2bin = new Hex2Bin( end_addr );
...
I assume that the Hex2Bin is as follows:
public class Hex2Bin
{
private short endAddress;
public Hex2Bin( short endAddress )
{
this.endAddress = endAddress;
}
}
this will allow you to use the value of end_addr from Program.cs
Another approach is to pass it directly to the method that will make use of it:
Hex2Bin.Method(end_addr);
and in the Hex2Bin file:
public static void Method(short endAddress)
{
//... do the work here
}
Given your background in C, I think you may be mixing runtime with compile time issues.
However, in Hex2Bin.cs, you can create a static method that updates a static variable.
class Hex2Bin
{
static short end_addr = 0x0000;
static void updateEndAddr(short endAddr)
{
end_addr = endAddr;
}
}

C# - How to access a static class variable given only the class type?

This is my first time posting on Stack Overflow, so hopefully I did everything right and you guys can help.
I'm wondering if in C# there's a way to access a static variable belonging to a class, when given only the type of the class. For example:
public class Foo
{
public static int bar = 0;
}
public class Main
{
public void myFunc(Type givenType)
{
int tempInt = ??? // Get the value of the variable "bar" from "Foo"
Debug.WriteLine("Bar is currently :" + tempInt);
}
}
// I didn't run this code through a compiler, but its simple enough
// that hopefully you should get the idea...
It's hard to describe the context of needing to know this, but I'm making a game in XNA and I'm trying to use reference counting to reduce the complexity of the design. I have objects in the game and power-ups that can apply an effect them (that stays on the objects). Power-ups can die but their effects can still linger on the objects, and I need to keep track of if any effects from a power-up are still lingering on objects (thus, reference counting). I plan to make a "PowerUpEffect" class (for each type of power-up) with a static integer saving the number of objects still affected by it, but the design of the rest of the game doesn't work well with passing the PowerUpEffect all the way down to the object for it to call a method of the PowerUpEffect class.
I'm hoping to pass only the PowerUpEffect's type (using something like "typeOf()") and use that type to reference static variables belonging to those types, but I have no idea how to do it or if it's even possible.
I'd be glad to even find work-arounds that don't answer this questions directly but solve the problem in a simple and elegant design. =)
Help! (and thanks!)
If you only have the Type handle, you can do this:
var prop = givenType.GetProperty("bar");
var value = prop.GetValue(null);
I would use a Dictionary instead, which are probably the most concise way of mapping one set of values to another. If you are associating int values with Types, then do something like:
public static readonly Dictionary<Type, int> sTypeValues =
new Dictionary<Type, int>
{
{ typeof(Type1), 5 },
{ typeof(Type2), 10 },
{ typeof(Type3), 2 },
{ typeof(Type4), 3 },
{ typeof(Type5), -7 }
};
your function then becomes:
public void myFunc(Type givenType)
{
int tempInt = sTypeValues[givenType];
Debug.WriteLine("Bar is currently :" + tempInt);
}
int tempInt = (int) givenType.GetField("bar").GetValue(null);
Okay, so you have a collection of powerups, and you want to have an integer associated with each of those powerups. Rather than having a lot of classes, each with a static integer, you can have a single static collection which holds onto all of the powerups and their associated integer values.
public static class MyPowerupInfo
{
public static Dictionary<PowerUp, int> PowerUps {get; private set;}
static MyPowerupInfo
{
PowerUps = new Dictionary<PowerUp, int>();
PowerUps.Add(*some power up object goes here*, 0);
//TODO add other power ups
}
}
Then to use it you can do something like:
int powerupCount = MyPowerupInfo.PowerUps[wickedAwesomePowerup];
or:
public static void IncrementPowerup(Powerup powerup)
{
MyPowerupInfo.PowerUps[powerup] = MyPowerupInfo.PowerUps[powerup]+1;
}
If am getting you correc, this might give you some idea:
using System;
using System.Reflection;
public class RStatic
{
private static int SomeNumber {get; set;}
public static object SomeReference {get; set;}
static RStatic()
{
SomeReference = new object();
Console.WriteLine(SomeReference.GetHashCode());
}
}
public class Program
{
public static void Main()
{
var rs = new RStatic();
var pi = rs.GetType().GetProperty("SomeReference", BindingFlags.Static | BindingFlags.Public); // i have used GetProperty in my case
Console.WriteLine(pi.GetValue(rs, null).GetHashCode());
}
}
Are you assuming if the name of the field you're trying to access (for example, for the class "foo", the field "bar") is a different field based on the Type parameter?
If the name of the field is known based on a finite number of allowable types, you should be able to determine it with a switch statement. For example:
public class Foo
{
public static int bar = 0;
}
public class Baz
{
public static int bing = 0;
}
public class Main
{
public void myFunc(Type givenType)
{
switch (givenType.ToString())
{
case "Foo":
Debug.WriteLine("Bar is currently :" + Foo.bar);
break;
case "Baz":
Debug.WriteLine("Bing is currently :" + Baz.bing);
break;
}
}
}

C# Struct / Lookup Table

Say I have a struct declared like the following:
public struct Test
{
public static int Width = 5;
...
public static int[] Value = new int[1]{ 0 };
}
Now what I want to do is call this from within another struct, but I have to clue how. What I'm trying to do would (in my mind) look like the following:
public struct AnotherStruct
{
public (type of struct) this[int key]
{
get
{
switch(key)
{
case 1:
return (another struct);
default:
return null;
}
}
}
}
My end goal is that I want to use code that looks like the following, without having to create an instance of the object:
structobject s = new AnotherStruct[5];
So this 'lookup table' will be created in another project and built, then called as a dll from my main project. Since I'm building the dll elsewhere and calling it, I'm hoping that I can get the dll loaded into memory once, and then I can just reference that memory from my main project. Then I'll have one allocated portion of memory and my code will just reference it, avoiding the need to create individual instances of this lookup table (thus avoiding the time overhead it takes to allocate the memory and store the new instance). The time I'd save would be hugely beneficial in the long run, so I'm hoping I can get this to work somehow.
I hope this isn't too confusing, but let me know if any clarification is needed.
Edit
This is being used on a website, so really I need an object that persists across all connections and is created once when the code is initially loaded. Same idea, but maybe that will make for a simpler solution?
Solution #2. Forgo the whole ID idea and just use the structure type and generics.
public struct St1
{
}
public struct St2
{
}
public class Factory<T>
where T : struct
{
static T _new = new T(); //cached copy of structure
public static T New { get { return _new; } }
}
class Program
{
static void Main(string[] args)
{
St1 x1 = Factory<St1>.New;
St1 x2 = Factory<St1>.New;
St1 x3 = Factory<St1>.New;
St2 y1 = Factory<St2>.New;
St2 y2 = Factory<St2>.New;
}
}
Solution #1. Using a common interface for all the structures and a dictionary collection
public interface IStr { }
public struct St1 : IStr
{
public static int ID = 1;
}
public struct St2 : IStr
{
public static int ID = 2;
}
public class StructFactory : System.Collections.ObjectModel.KeyedCollection<int, IStr>
{
public static StructFactory Default = new StructFactory();
protected override int GetKeyForItem(IStr item)
{
FieldInfo finfo = item.GetType().GetField("ID",
BindingFlags.Static | BindingFlags.Public);
return (int)finfo.GetValue(item);
}
public StructFactory()
{
Add(new St1());
Add(new St2());
}
}
class Program
{
static void Main(string[] args)
{
St1 x = (St1)StructFactory.Default[1];
St2 y = (St2)StructFactory.Default[2];
}
}
The syntax you use above won't work since it means "create an array of AnotherStruct with five elements in it." As mentioned in a comment, however, you really should look into using a factory pattern.
However, if you really want to use the pattern above, you could change it up slightly. Have your AnotherStruct array hold Type instances of each of your structs. Then, your "creation" line would look more like:
structobject s = (structobject)Activator.CreateInstance(AnotherStruct[5]);
You can use reflection on the Assembly (since you are wrapping it in a DLL) to get those Type objects.
And finally, unless you have a really good reason for using struct (and understand all of the nuances, of which there are several), stick with class.

Categories

Resources