Reputation: 49
I need to get a random class, store in to a "global class" variable (so i can access it in other methods), but i cannot find any good way to do it, what i've been trying to do is work with object variables... I'm coming from python to c#, so the properties of object variables looks kind of a mystery to me... I have been searching how to make it work, but i could not find a proper way to do it without a bunch of if statements...
//There might not be all the necessary namespaces to run this code
using UnityEngine; //where the random.range() came from
public class man1 //Initialization of the first class
{
public int val = 1;
}
public class man2 //Initialization of the second class
{
public int val = 2;
}
public class man3 //Initialization of the third class
{
public int val = 3;
}
public class allMan
{ //Where all classes 'merge'
private object chosenMan; //Where the chosen it's going to be stored
public allMan() //Constructor
{
//Have all man in one array to easily get the chosen from index
object[] men = new object[] { new man1(), new man2(), new man3() };
var choice = Random.range(0, men.Length); //Randomly get the index
chosenMan = men[choice]; // Atribute the chosen class
}
public void doActionWithChoosedMan()
{
Console.WriteLine(chosenMan.val); //ERROR
}
}
How should i approach this problem? Thanks.
Upvotes: 0
Views: 205
Reputation: 9499
While @programtreasures posts a good immediate solution, you need to consider that C# is a strongly typed language. That means that, unlike python and javascript, you can't attempt to randomly access undeclared properties and methods on an object.
Note that in the case you've demonstrated, there is no difference across your 3 classes. They should simply be instances of a type Man
, like so
class Man
{
public int Val { get; set; } // try to use properties to hold externally accessible values
}
public class AllMan // c# uses Pascal casing
{ //Where all classes 'merge'
private Man chosenMan; //Where the chosen it's going to be stored
public AllMan() //Constructor
{
//Have all man in one array to easily get the chosen from index
var men = new Man[] { new Man() { Val = 1 }, new Man() { Val = 2 }, new Man() { Val = 3 } };
var choice = Random.range(0, men.Length); //Randomly get the index
chosenMan = men[choice]; // Atribute the chosen class
}
public void DoActionWithChoosedMan()
{
Console.WriteLine(chosenMan.Val);
}
}
For something that requires you to have differences on types, you could declare an interface, e.g.
interface IMan
{
int Val {get;}
}
And then have your different types implement this:
class Man1 : IMan
{
public int Val {get;} = 1;
public string SomethingElse {get;set;}
}
class Man2 : IMan
{
public int Val {get;} = 2;
public boolean AmICool {get;set;}
}
Then you could run the code as above, but changing the type of chosenMan
field to be IMan
.
Additionally, you might also want to implement an abstract
base class to hold just the property you require and then stack the rest of things on top. That depends on whether the default initialization is shared across classes and whether there is anything else common that requires an implementation.
Upvotes: 3
Reputation: 20
Solution 1: In doActionWithChoosedMan() method you are directly using the chosenMan but it is not the correct way of doing.
before using it you have to check the type of the chosenMan by
if(chosenMan.GetType() == typeof(man1)){
man1 man11= new man1();
Console.WriteLine(man11.val); //No Error
}if(chosenMan.GetType() == typeof(man2)){
man1 man22= new man1();
Console.WriteLine(man22.val); //No Error
}if(chosenMan.GetType() == typeof(man3)){
man1 man33= new man1();
Console.WriteLine(man33.val); //No Error
}
Same way you have to check for all the object then create the object of the main class which is here "man1" and then you will be able to access the "val".
Solution 2: You can make chosenMan dynamic.
Upvotes: 0
Reputation: 4298
One variable is typed as object by the compiler and all instance members will be verified as valid by the compiler. The other variable is typed as dynamic and all instance members will be ignored by the compiler and called by the DLR at execution time.
You can use dynamic
instead of object
public class allMan
{
//Where all classes 'merge'
private dynamic chosenMan; //Where the chosen it's going to be stored
public allMan() //Constructor
{
//Have all man in one array to easily get the chosen from index
object[] men = new object[] { new man1(), new man2(), new man3() };
var choice = Random.range(0, men.Length); //Randomly get the index
chosenMan = men[choice]; // Atribute the chosen class
}
public void doActionWithChoosedMan()
{
Console.WriteLine(chosenMan.val); //ERROR
}
}
Upvotes: 2