I have some classes that all implement a certain interface. I want to store a unique string in each class that I can get without creating an object for that class. I searched through a lot of posts her开发者_高级运维e already and couldn't find an answer.
If I create an object for each class, then what I want is simply:
class X:IBase{ string m = "x";}
class Y:IBase{string m = "x";}
class Z:IBase{string m = "x";}
class interface IBase{ string m;}
static int Main(){
IBase[] arr = {new X(), new Y(), new Z()};
foreach(IBase b in arr){
Console.WriteLine(b.m);
}
}
But I want to do this without creating an object. So I want to do this:
class X:IBase{ static string m = "x";}
class Y:IBase{ static string m = "x";}
class Z:IBase{ static string m = "x";}
class interface IBase{ //no static fields allowed}
static int Main(){
Type[] arr = {X, Y, Z};
foreach(Type t in arr){
Console.WriteLine(t.m); //error, cannot resolve symbol m
}
}
Am I missing something obvious or is this just impossible?
The reason I don't want to create an object is because I want to display this string at the start, when I don't need any objects. I only create an object when I need to to save space.
The obvious thing here is to have m
be an attribute of an abstract base class and assign a new value in the static constructors of your derivative classes.
You can also use System.Reflection
for this, if you don't want to go the easy route (abstract base class).
You can also add Attributes to your classes and look up the values there.
Here is the easy route with abstract base classes:
abstract class AbstractBase: IBase { protected static string m = "?"; }
class X: AbstractBase { static X() { m = "x"; }}
class Y: AbstractBase { static Y() { m = "y"; }}
class Z: AbstractBase { static Z() { m = "z"; }}
interface IBase { //no static fields allowed}
}
static int Main(){
AbstractBase[] arr = {new X(), new Y(), new Z()};
foreach(AbstractBase t in arr){
Console.WriteLine(t.m); // :)
}
}
EDIT: I fixed the code sample to remove the compiler errors. Sorry for posting code that wasn't quite right. Doing so, I noticed that the foreach
loop can't really be done without creating objects, since (unlike python) c# won't let you just refer to a type and call methods on it - that is the job of System.Reflection
, so, as others have pointed out, you will want to check out GetMember
and friends.
Reflection is your friend:
interface IBase { }
class X : IBase { static string m = "x";}
class Y : IBase { static string m = "y";}
class Z : IBase { static string m = "z";}
static void Main()
{
Type[] arr = { typeof(X), typeof(Y), typeof(Z) };
foreach (Type t in arr)
{
FieldInfo fieldInfo = t.GetField("m",
BindingFlags.Static | BindingFlags.NonPublic);
Console.WriteLine(fieldInfo.GetValue(null));
}
}
Note how Type[] arr = {X, Y, Z};
has been changed into Type[] arr = { typeof(X), typeof(Y), typeof(Z) };
in order to get the Type
object for each of the types.
Type[] arr = new[] { typeof(X), typeof(Y), typeof(Z) };
foreach(Type t in arr)
{
FieldInfo fi = t.GetField("m", BindingFlags.Static | BindingFlags.NonPublic);
// or PropertyInfo pi = t.GetProperty(...);
string m = (string)fi.GetValue(null);
// GetValue(null, null);
}
You need to use Reflection
to access that property....
Like as below ( Example )
MyTypeb = typeof(Myfieldb);
FieldInfo Myfieldinfob = MyTypeb.GetField("field",BindingFlags.NonPublic|BindingFlags.Static);
Console.Write("{0}; ", Myfieldinfoa.GetValue(Myfielda));
精彩评论