Ok... in Objective C you can new up a subclass from a static method in the base class with 'new this()' because in a static method, 'this' refers to the class, not the instance. That was a pretty damn cool find when I first found it and I've used it often.
However, in C# that doesn't work. Damn!
So... anyone know how I can 'new' up a subclass from within a static base class method?
Something like this...
public class MyBaseClass{
string name;
public static Object GimmeOne(string name){
// What would I replace 'this' with in C#?
return new this(name);
}
public MyBaseClass(string name){
this.name = name;
}
}
// No need to write redundant constructors
public class SubClass1 : MyBaseClass{ }
public class SubClass2 : MyBaseClass{ }
public class SubClass3 : MyBaseClass{ }
SubClass1 foo = SubClass1.GimmeOne("I am Foo");
And yes, I know I can (and normally would) just use the constructors directly, but we have a specific need to call a shared member on the base class so that's why I'm asking. Again, Objective C let's me do this. Hoping C# does too.
So... any takers?
C# doesn't have any exact equivalent to that. However, you could potentially get around this by using generic type constraints like this:
public class MyBaseClass
{
public string Name { get; private set; }
public static T GimmeOne<T>(string name) where T : MyBaseClass, new()
{
return new T() { Name = name };
}
protected MyBaseClass()
{
}
protected MyBaseClass(string name)
{
this.Name = name;
}
}
The new() constraint says there is a parameterless constructor - which your didn't but we make it private to hide that from consumers. Then it could be invoked like this:
var foo = SubClass1.GimmeOne<SubClass1>("I am Foo");
Sorry, you can't do this. C# is morally opposed to static method inheritance. That GimmeOne method will never have any type other than MyBaseClass, and calling it from SubClass1 doesn't matter- it's still "really" a MyBaseClass call. The Reflection libraries could do this construction, but you'd never get anything other than a MyBaseClass out of it.
If you're calling a static method, presumably you know which subclass you're calling it from. Create a different factory method for each subclass. If you're actually trying to do this by instance, you should probably use a non-static virtual factory method (which will automatically call the most derived form of the function, which is probably what you want) instead.
Related
I was wondering if it's possible (even via reflection et similia) to get the caller derived-class inside of a called base-class static method.
For example, I've a base-class with a static method defined:
public MyBaseClass {
public static void MyBaseClassStaticMethod() { /** ... **/ }
}
and a derived-from-it class:
public MyDerivedClass : MyBaseClass { }
then I call:
MyDerivedClass.MyBaseClassStaticMethod()
Is it possibile, inside of method MyBaseClassStaticMethod, to know which is the caller derived type?
(i.e. MyDerivedClass)
I just need a string...
Generics in following way can be used to solve your scenario
public class BaseClass<TDerived> where TDerived : BaseClass<TDerived>
{
public static void LogCallerType()
{
Console.WriteLine(typeof(TDerived).Name);
}
}
public class FooClass : BaseClass<FooClass> { }
public class BooClass : BaseClass<BooClass> { }
class Program
{
static void Main(string[] args)
{
FooClass.LogCallerType();
BooClass.LogCallerType();
}
}
This will in turn output the following
1. FooClass
2. BooClass
No, this is not possible - by no means. static methods are not polymorphal and as such this information simply doesn't exist.
Consider redesigning your code.
Update:
Upon compilation, the compiler replaces MyDerivedClass with the class the static method is actually declared on, in your case MyBaseClass.
So even in the IL you don't see MyDerivedClass. The information exists only in your source code. It doesn't exist in your compiled assembly.
A static method is statically bound to a certain class and does not really participate in the inheritance-chain. Thus it does not exist in the derived class. The static method therefor does not know that it was actually used in the derived class.
You can however - through a compiler-trick - access the static member from your derived class. As of this post on MSDN-forum a static member-access from a derived class is translated to a call from the base-class containing the static member. So MyDerivedClass.MyBaseClassStaticMethod is translated to MyBaseClass.MyBaseClassStaticMethod. Thus MethodBase.GetCurrentMethod().DeclaringType will allways return MyBaseClass.
So in short: no, it´s not possible to get the derived type from a static member.
First of all, the static method will not have access to the instance that is calling it. A static method is different from a normal class method in that it does not have access the 'this' reference to a class instance.
If you passed 'this' as a parameter to the static method, then you can try casting it as follows. Assume you have a number of derived class which you want to test for.
public static void MyBaseClassStaticMethod(MyBaseClass callingInstance)
{
MyDerivedClass myDerivedClass = callingInstance as MyDerivedClass;
MyDerivedClass2 myDerivedClass2 = callingInstance as MyDerivedClass2;
MyDerivedClass3 myDerivedClass3 = callingInstance as MyDefivedClass3;
...
// test for which derived class is calling
if (myDerivedClass != null)
...
else if (myDerivedClass2 != null)
...
...
}
ok Im back with another question... It seems you when you assign base objects as another object , the base object is turned into that object, but still is without its properties for example.
public class MyObjectBase {
public void Begin() {
}
{
public class OneOfMyObjects : MyObjectBase {
public void Begin() {
base.Begin();
//do stuff
}
}
public class ManagmentClass {
public MyObjectBase myCurrentObject;
//called a only one when the program starts
public void Start() {
Mymethod(new OneOfMyObjects());
}
//generic method
public void Mymethod<T>(T Objectclass) where T : MyObjectBase {
myObject = Objectclass
myObject.Begin(); // compiler error, non existent in MyObjectBase
myObject.GetType().ToString() //returns "OneOfMyObjects"
}
}
Of course, the compiler can't find "Begin()" since begin doesn't originally exists in MyBaseObject.
I'm doing a conversion between a custom language similar to Ruby to C#(above), but this Ruby-like language doesn't come across this "problem" I'm having. It seems to compile it. Is there something in .NET4 that can solve this issues that I'm forgetting?
Well, you could just use dynamic typing:
dynamic myObject;
... but your Mymethod method can't really accept any instance of a MyObjectBase... it must have a Begin method, for example. Using dynamic typing, you'll only discover when that's not the case at execution time.
Rather than directly porting some code written for a different language with different idioms, you should think about the higher level goal that code is trying to achieve, and the most idiomatic way of achieving the same goal in C#. We can't guide you on that without more information.
Give this a whirl. The issue is that you're using a base class that doesn't provide a definition of Begin(and you knew that, just reiterating). So, the thing to do is to provide a way for the base class to have a Begin() method. In the below example, MyObjectBase is an abstract class and Begin() is an abstract method. This means that MyObjectBase will never have a definition for Begin(), but it forces all derived classes to provide a definition for Begin(). So, for example:
MyObjectBase obj1 = new MyObjectBase();
obj1.Begin(); //Won't Compile
OneOfMyObjects obj2 = new OneOfMyObjects();
obj2.Begin(); //Compiles if and only if OneOfMyObjects
//class has a definition for Begin().
Also, I'm usually programming in C++ so this may not be 100% best-practice for C#, but it's compile-able. I also changed the scope of Begin. Protected is used when you want a derived class to access something in a base class, but it isn't necessarily the scope you use when dealing with something that's derived. Begin is being accessed from outside of the base and derived classes so it needs to be public.
public abstract class MyObjectBase
{
public abstract void Begin();
}
public class OneOfMyObjects : MyObjectBase
{
public override void Begin()
{
//do stuff
}
}
public class ManagmentClass
{
public MyObjectBase myCurrentObject;
//called a only one when the program starts
public void Start()
{
Mymethod(new OneOfMyObjects());
}
//generic method
public void Mymethod<T>(T Objectclass) where T : MyObjectBase {
MyObjectBase myObject = Objectclass;
myObject.Begin(); // Shouldn't throw an error any more
myObject.GetType().ToString(); //returns "OneOfMyObjects"
}
}
I was wondering if it's possible (even via reflection et similia) to get the caller derived-class inside of a called base-class static method.
For example, I've a base-class with a static method defined:
public MyBaseClass {
public static void MyBaseClassStaticMethod() { /** ... **/ }
}
and a derived-from-it class:
public MyDerivedClass : MyBaseClass { }
then I call:
MyDerivedClass.MyBaseClassStaticMethod()
Is it possibile, inside of method MyBaseClassStaticMethod, to know which is the caller derived type?
(i.e. MyDerivedClass)
I just need a string...
Generics in following way can be used to solve your scenario
public class BaseClass<TDerived> where TDerived : BaseClass<TDerived>
{
public static void LogCallerType()
{
Console.WriteLine(typeof(TDerived).Name);
}
}
public class FooClass : BaseClass<FooClass> { }
public class BooClass : BaseClass<BooClass> { }
class Program
{
static void Main(string[] args)
{
FooClass.LogCallerType();
BooClass.LogCallerType();
}
}
This will in turn output the following
1. FooClass
2. BooClass
No, this is not possible - by no means. static methods are not polymorphal and as such this information simply doesn't exist.
Consider redesigning your code.
Update:
Upon compilation, the compiler replaces MyDerivedClass with the class the static method is actually declared on, in your case MyBaseClass.
So even in the IL you don't see MyDerivedClass. The information exists only in your source code. It doesn't exist in your compiled assembly.
A static method is statically bound to a certain class and does not really participate in the inheritance-chain. Thus it does not exist in the derived class. The static method therefor does not know that it was actually used in the derived class.
You can however - through a compiler-trick - access the static member from your derived class. As of this post on MSDN-forum a static member-access from a derived class is translated to a call from the base-class containing the static member. So MyDerivedClass.MyBaseClassStaticMethod is translated to MyBaseClass.MyBaseClassStaticMethod. Thus MethodBase.GetCurrentMethod().DeclaringType will allways return MyBaseClass.
So in short: no, it´s not possible to get the derived type from a static member.
First of all, the static method will not have access to the instance that is calling it. A static method is different from a normal class method in that it does not have access the 'this' reference to a class instance.
If you passed 'this' as a parameter to the static method, then you can try casting it as follows. Assume you have a number of derived class which you want to test for.
public static void MyBaseClassStaticMethod(MyBaseClass callingInstance)
{
MyDerivedClass myDerivedClass = callingInstance as MyDerivedClass;
MyDerivedClass2 myDerivedClass2 = callingInstance as MyDerivedClass2;
MyDerivedClass3 myDerivedClass3 = callingInstance as MyDefivedClass3;
...
// test for which derived class is calling
if (myDerivedClass != null)
...
else if (myDerivedClass2 != null)
...
...
}
I'm probably doing this totally wrong..
public class BaseClass
{
public string result { get; set; }
public BaseClass(){}
public BaseClass(string x) {
result = doThing(x);
}
public virtual string doThing(string x)
{
return x;
}
}
public class DerivedClass : BaseClass
{
public DerivedClass(){}
public DerivedClass(string x):base(x){}
public override string doThing(string x)
{
return "override" + x;
}
}
I'd like for a new DerivedClass("test") to have a result of "overridetest" but it doesn't: it calls the base method of doThing. Am I missing something? Do I need to make an AbstractClass and have both BaseClass and DerivedClass inherit from that, Derived class also overriding methods?
The problem is that you are making a virtual call in the constructor. The mechanics of this issue and possible workarounds are detailed here.
In short, the overridden function has not yet been constructed when you enter the constructor of the base class, therefore the virtual function in the base class is called.
You can't access a subclass' instance member from a base class.
It calls the base class's doThing method because that is the only available doThing method as far as the base class is concerned. If you want an instance of each class call it's own doThing method, in your child class replace:
public DerivedClass(string x):base(x){}
with:
public DerivedClass(string x)
{
doThing(x);
}
From a design perspective, you should always be wary of "doing things" during a constructor call. The purpose of a constructor is merely to get an instance of the class into a valid state for future use; it shouldn't try to "do" anything else or have any other side effects. If your object construction is a complicated affair, you might want to employ the Builder or Factory patterns to shield calling code from the complexity.
It's because your DerivedClass uses the base constructor and will set result as base.doThing("test") which is "test".
so you could change your DerivedClass to:
public class DerivedClass : BaseClass
{
public DerivedClass(){}
public DerivedClass(string x):base(x)
{
result="override"+x;
//or as result already be set as x, you can use: result="override" + result;
}
}
or as you said,
need to make an AbstractClass and have both BaseClass and
DerivedClass inherit from that, Derived class also overriding methods?
I've got an abstract class like this;
public abstract PropertyBase
{
public static System.Type GetMyType()
{
return !!!SOME MAGIC HERE!!!
}
}
I'd like to subclass it, and when I call the static GetMyType(), I'd like to return the subclass's type. So if I declare a subtype;
public class ConcreteProperty: PropertyBase {}
then when I call
var typeName = ConcreteProperty.GetMyType().Name;
I expect 'typeName' to be set to "ConcreteProperty." I suspect there's no way to do it, but I'm interested if anyone out there knows a way to get this info.
(The particular problem I'm trying to solve is the verbosity of dependency properties in WPF; I'd love to be able to do something like this;
class NamedObject : DependencyObject
{
// declare a name property as a type, not an instance.
private class NameProperty : PropertyBase<string, NamedObject> { }
// call static methods on the class to read the property
public string Name
{
get { return NameProperty.Get(this); }
set { NameProperty.Set(this, value); }
}
}
And I almost have an implementation, but I can't quite get the info I need out of my NameProperty class.)
You can partially achieve (1-level of inheritance deep) using generics:
class PropertyBase<T>
{
public static Type GetMyType() { return typeof (T); }
}
// the base class is actually a generic specialized by the derived class type
class ConcreteProperty : PropertyBase<ConcreteProperty> { /* more code here */ }
// t == typeof(ConcreteProperty)
var t = ConcreteProperty.GetMyType();
The subclassing bit will not work, because a static method is tied to a type. It is a method of a type, not a method of an instance. The subtype does not contain the static methods of a base type, because they are different types and the static method is tied to the base type. Even though the compiler might allow you to call a static method of a base class as through a derived class, it will in reality call the method from the base class. It's just syntax sugar. For the same reason you cannot "override" static methods in subclasses because it would make little sense.
Just wondering why would need to do something like this?
var typeName = ConcreteProperty.GetMyType().Name;
Anyhow you know the type while calling the method, you can simply do this as well..
var typeName = typeof(ConcreteProperty).Name;
Just in case you need to do this, you can use "shadowing" to override the implementation of base class in child class.
public class ConcreteProperty : PropertyBase {
public new static Type GetMyType {
//provide a new implementation here
}
}