Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
Question
Friday, July 11, 2008 11:34 AM
hi
assume that I have 3 classes which two of them are inheriting from one. I want to return the type name of the caller static method:
public abstract class Parent
{
...
public static string GetTypeStr()
{
??????????
}
...
}
public class Class1:Parent
{
...
}
public class Class2:Parent
{
...
}
MessageBox.Show(Class1.GetTypeStr());
MessageBox.Show(Class2.GetTypeStr());
All replies (18)
Friday, July 11, 2008 12:04 PM âś…Answered
The Parent.GetTypeStr() won't help.
The easiest approach is: don't make it static! If the semantic of that method depends on the calling object, then let it be a protected instance method; then the subclasses can just use this.GetTypeStr() [or just GetTypeStr()] and it will work:
protected string GetTypeStr() {return GetType().Name;}
Otherwise you're into messing with stack-frames etc, and it isn't pretty. You can query the calling *assembly* easily, but types are trickier... and inlining etc makes things even more complex.
Marc
Friday, July 11, 2008 11:59 AM
Hi,
I think you migh want to:
public string GetTypeStr(){
return Parent.GetTypeStr();
}
you could just put this in the parent class or in both Class1 and Class2.
Cheers,
John
Friday, July 11, 2008 12:10 PM
Maybe you want to consider declaring the method abstract like
public abstract class Parent
{
public abstract string Method();
}
public class Son1 : Parent
{
public override string Method()
{
//Do somthing if the type is Son1
}
}
public class Son2 : Parent
{
public override string Method()
{
//Do something if type is Son2
}
}
If this is not what you want can you be more explecit in what you are trying to do(the logic of your aplication). Becouse as far as I know there is no way of knowing the type of the children in a parent class.
Thanks,
Camilo
Friday, July 11, 2008 12:13 PM
Marc,
Are you sure?
| namespace Green |
| { |
| using System.Text.RegularExpressions; |
| class Grass |
| { |
| public static void Main() |
| { |
| string result = new ClassA().GetStuff(); |
| Console.WriteLine(result); |
| } |
| class Parent |
| { |
| public static string GetStuff() |
| { |
| return "hello world"; |
| } |
| } |
| class ClassA : Parent |
| { |
| public string GetStuff() |
| { |
| return "My parent says: " + Parent.GetStuff(); |
| } |
| } |
| } |
| } |
| // |
| // Output: |
| // |
| // My parent says: hello world |
| // |
| // Done. |
Friday, July 11, 2008 12:16 PM
> Are you sure?
OK, now "return the type name of the caller" using that approach...
Marc
Friday, July 11, 2008 12:23 PM
| namespace Green |
| { |
| using System.Text.RegularExpressions; |
| using System.Diagnostics; |
| class Grass |
| { |
| public static void Main() |
| { |
| string result = new ClassA().GetStuff(); |
| Console.WriteLine(result); |
| } |
| class Parent |
| { |
| public static string GetStuff() |
| { |
| return new StackTrace(false).GetFrame(1).GetMethod().DeclaringType.Name.ToString(); |
| } |
| } |
| class ClassA : Parent |
| { |
| public string GetStuff() |
| { |
| return "My parent says: " + Parent.GetStuff(); |
| } |
| } |
| } |
| } |
| // |
| // Output: |
| // |
| // My parent says: ClassA |
| // |
| // Done. |
Friday, July 11, 2008 12:30 PM
So as I already mentioned, you're into messing with stackframes. Which can easily be confused during JIT inlining.
It also doesn't correctly respect inheritance - it returns the DeclaringType, not the actual type of the caller; for example:
| class ClassB : ClassA |
| { |
| public new string GetStuff() { return base.GetStuff(); } |
| } |
with:
| string result = new ClassB().GetStuff(); |
And it claims the caller is a ClassA; well, it isn't - it is a ClassB, using a method from ClassA. Of course, this is open to interpretation of what you consider the caller to be, but for my money GetType() is a *lot* simpler.
Marc
Friday, July 11, 2008 12:54 PM
I was trying out your code and if you try to do something like this:
Parent p = new ClassA();
Console.WriteLine(p.GetStuff());
you get this error
Error 2 Member 'ConsoleApplication1.Parent.GetStuff()' cannot be accessed with an instance reference; qualify it with a type name instead C:\Documents and Settings\user\Local Settings\Application Data\Temporary Projects\ConsoleApplication1\Program.cs 15 31 ConsoleApplication1
Also if you tried
Parent.GetStuff();
And returned the class from where I was calling the method.
Thanks,
Camilo.
Friday, July 11, 2008 1:11 PM
> I was trying out your code
You might want to clarify which of the umpteen variants you are trying/responding to... the web UI doesn't offer a threaded view...
Marc
Friday, July 11, 2008 1:14 PM
Sorry about that I was talking about the rtizan[0] solution.
thanks,
Olimac
Friday, July 11, 2008 1:21 PM
Personally I wouldn't listen to anything that rtizan[0] has to say. Coming into this forum after a 30 hr shift might be good way to unwind. But it's not helping anybody else.
There is no way to access instance data from a static method unless you pass it that instance data in the first place, in which case you might as well talk to the instance directly (Instead of accessing it indirectly through the StackTrace). Must remember to read the question next time.
Cheers,
John :-[
Monday, July 14, 2008 5:50 AM
thank you all for the replies. as I experienced different solutions I can agree with Marc's first answer.
Saturday, March 21, 2009 10:49 PM
I have to ask this question again, because there is no solution here. Solution in which we don't use static method do not for me, because it's costly to make the instance of object everty time, when I need to call this method.
Have you any other ideas how can I do this? is it posible in general?
Saturday, March 21, 2009 10:58 PM
Option 1: use stack frames, and accept the JIT risks
Option 2: refactor
Perhaps if you could set a little context, we could help more. For example, why do these methdods have to be static? Would singletons be a half-way house? etc
Marc [C# MVP]
Sunday, March 22, 2009 12:54 AM
This seemed to work.
| public abstract class Parent |
| { |
| public static string GetTypeStr<T>() where T : Parent, new() |
| { |
| T obj = new T(); |
| return obj.GetType().ToString(); |
| } |
| } |
| public class Class1 : Parent |
| { |
| public Class1() |
| { |
| } |
| } |
| public class Class2 : Parent |
| { |
| public Class2() |
| { |
| } |
| } |
| Console.WriteLine(Class1.GetTypeStr<Class1>()); |
| Console.ReadLine(); |
Cheat. Make it generic.
Rudedog =8^DMark the best replies as answers. "Fooling computers since 1971."
Sunday, March 22, 2009 1:06 AM
Take your pick!
| public abstract class Parent<U> where U:Parent<U> , new() |
| { |
| public static string GetTypeStr<T>() where T : Parent<T>, new() |
| { |
| T obj = new T(); |
| return obj.GetType().ToString(); |
| } |
| public static string GetTypeStr() |
| { |
| return new U().GetType().ToString(); |
| } |
| } |
| public class Class1 : Parent<Class1> |
| { |
| public Class1() |
| { |
| } |
| } |
| public class Class2 : Parent<Class2> |
| { |
| public Class2() |
| { |
| } |
| } |
Mark the best replies as answers. "Fooling computers since 1971."
Sunday, March 22, 2009 7:52 PM
Marc Gravell said:
Option 1: use stack frames, and accept the JIT risks
Option 2: refactor
Perhaps if you could set a little context, we could help more. For example, why do these methdods have to be static? Would singletons be a half-way house? etc
Version with stack frames doesn't work if we don't declare non-static method in child-class. what do you mean by refactor?
The contex is that I have MANY inherited classes and method GetTableName() which return name of table using the name of class. And I want to know this result for each class without its creation.
I tried to use Reflection but it had no effect. So, if it's not simple way to solve this problem i should turn it down.
Rudedog2 said:
This seemed to work.
Cheat. Make it generic.
Thanx for your answer. it's working variant, but i think not once that i need.
Sunday, March 22, 2009 8:09 PM
Ah. Context.
DoubleCheck!!! Which classes contain GetTableName()? Answer, all of the inherited classes. Is creating a private field not an option?Mark the best replies as answers. "Fooling computers since 1971."