如何以可以从 C# 中的其他方法访问的方式存储随机类变量?



我需要获取一个随机类,存储在"全局类"变量中(这样我就可以用其他方法访问它),但我找不到任何好的方法去做,我一直在尝试做的是使用对象变量......我是从python到c#的,所以对象变量的属性对我来说看起来有点神秘......我一直在寻找如何使其工作,但是如果没有一堆if语句,我找不到正确的方法来做到这一点......

//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
}
}

我应该如何处理这个问题?谢谢。

虽然@programtreasures发布了一个很好的即时解决方案,但您需要考虑 C# 是一种强类型语言。这意味着,与python和javascript不同,你不能尝试随机访问对象上未声明的属性和方法。

请注意,在您演示的情况下,您的 3 个类之间没有区别。它们应该只是类型Man的实例,就像这样

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

对于需要您在类型上存在差异的东西,您可以声明一个接口,例如

interface IMan
{
int Val {get;}
}

然后让你的不同类型实现这一点:

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

然后,您可以按上述方式运行代码,但将chosenMan字段的类型更改为IMan

此外,您可能还希望实现一个abstract基类,以仅保存所需的属性,然后将其余内容堆叠在顶部。这取决于默认初始化是否跨类共享,以及是否有任何其他需要实现的常见内容。

编译器将一个变量类型化为对象,编译器将验证所有实例成员是否有效。另一个变量类型为动态变量,编译器将忽略所有实例成员,并在执行时由 DLR 调用。

您可以使用dynamic而不是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
}
}

解决方案 1:在 doActionWithChoosedMan() 方法中,您直接使用 chosenMan,但这不是正确的方法。

在使用它之前,您必须检查所选人的类型 由

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
}

同样,您必须检查所有对象,然后创建主类的对象,该对象位于"man1",然后您将能够访问"val"。

解决方案2:您可以使选择的人动态化。

最新更新