I just spent hours being confused by an NullReferenceException where I thought there shouldn't be one. I was constructing a class like so:
public class MyClass : MyBase<Foo>
{
public MyClass()
{
base.Method(Foo.StaticField);
}
}
where
public class MyBase<T>
{
private SomeObject bar = new SomeObject();
public void Method(object o)
{
this.bar.AnotherMethod(o); // exception thrown here
}
}
Basically my IL was the following:
ctorIl.Emit(OpCodes.Ldarg_0);
ctorIl.Emit(OpCodes.Ldsfld, staticField);
ctorIl.Emit(OpCodes.Box, typeof(FieldType));
ctorIl.Emit(OpCodes.Call, parentMethod);
ctorIl.Emit(OpCodes.Ret);
and I finally figured that it must be that bar was not being instantiated. I constructed my class in C# and compiled it and found the only difference was that the following should be above the IL above:
ctorIl.Emit(OpCodes.Ldarg_0);
ctorIl.Emit(OpCodes.Call, parentCtor);
// as above
With these lines, my code now works as expected.
So my questions are:
Why do we need to explicitly call the base constructor to instantiate fields?
Is there a legitimate use of not calling the base constructor?
...and if not, why does the CLR accept it as a valid program?
because it isn't automatic, and it allows compilers and IL code to decide both when and if to call the base constructor
well, you can actually instantiate types without using any constructors whatsoever... edge case, sure; but allowed
because it is allowed
Note that you can actually emit a simple constructor (including base call) in a single method:
typeBuilder.DefineDefaultConstructor();
Related
Firstly, sorry for my English. I hope i can explain my problem.
I have class like this
public class CarCommandExecutorBase
{
protected readonly ICarCommand CarCommand;
public CarCommandExecutorBase(ICarCommand carCommand)
{
CarCommand = carCommand;
}
}
Also i have class like this
public class CarStringCommandExecutor : CarCommandExecutorBase, IStringCommand
{
public CarStringCommandExecutor(Car car)
{
// this Constructor gives me an error.
}
public void ExecuteCommand(string commandObject)
{
}
}
Error message:
[![error][1]][1]
What's the reason and how can i fix it? Thanks.
Since the only constructor in CarCommandExecutorBase is defined like this
public CarCommandExecutorBase(ICarCommand carCommand)
{
CarCommand = carCommand;
}
you have to pass an ICarCommand when creating an instance of CarCommandExecutorBase.
You have to provide an ICarCommand through the constructor of CarStringCommandExecutor, because when instantiating a derived type the base constructor(s) also get called.
See this answer for more detailed information about this: https://stackoverflow.com/a/1882778/8450550
You could do something like this to solve this error:
public class CarStringCommandExecutor : CarCommandExecutorBase, IStringCommand
{
...
public CarStringCommandExecutor(Car car, ICarCommand carCommand)
: base(carCommand) // base() points to the constructor of the base class
{
...
}
or maybe this
public class CarStringCommandExecutor : CarCommandExecutorBase, IStringCommand
{
...
public CarStringCommandExecutor(Car car)
: base(null) // passing null but be aware of NullReferenceExceptions
{
...
}
or you add another constructor to CarCommandExecutorBase which expects no arguments:
public class CarCommandExecutorBase
{
protected readonly ICarCommand CarCommand;
public CarCommandExecutorBase(ICarCommand carCommand)
{
CarCommand = carCommand;
}
// mark this constructor as protected, so only deriving types can call it
protected CarCommandExecutorBase()
{
}
}
Which solution works best in your case is up to you.
One of the things that isn't immediately apparent, thanks to "compiler magic", about a C# class is that every class has a constructor
It needs to be this way because it's a rule that object construction happens in a tree; you construct some class Z which inherits from Y which inherits from X which inherits from object, and Z's cosntructor invokes Y's invokes X's invokes object's, then they finish, in order of object, X, Y, Z and you have your nicely constructed thing - every constructor on the way up the tree had its chance to do its init and ready the object for use (the part of it that each constructor was responsible for)
Even classes that don't seem to have constructors, have constructors:
class X {
}
If you don't provide a constructor, C# provides one for you. You never see it in your source code; just imagine that in between reading the file and compiling it, the compiler inserts it for you. It takes no parameters, has no code, and does nothing other than call its base:
class X {
X():base() { } //C# invisibly writes this for you
}
If you provide a constructor but don't write the base... bit, C# puts base() in for you behind the scenes (and it always calls the no-argument base()) but critically it doesn't provide an empty constructor if you provided one already
This means if you have a class like:
class X{
X(string message){
...
}
}
Your class X has a constructor, so C# won't provide the empty one, so now anything that tries to construct your class must provide a string message:
X x = new X("hello");
If you now inherit from X, you might do one of 3 things (with Y):
class Y:X{
}
You don't add a constructor, C# adds one, but it just dumbly calls base(), which doesn't work because there is no constructor in X that takes no args:
class Y:X{
Y():base() { }
}
You add a constructor but leave off the base bit. C# adds it, again just literally as base() - this also doesn't work for the same reason
class Y:X{
Y(int myArg) //c# adds base() in here for you
{
...
}
}
You add a constructor that includes a call to base and because you know your base class only has a constructor with a string arg, you pass one:
class Y:X{
Y(int myArg) : base("hello")
{
...
}
}
So you're in scenario 2, and you either need to:
Add a no-arg constructor to the base class so that c#'s auto-inserted stuff works or,
Add a call to base(...) with a suitable argument, to stop C# from putting a base() in
I've left out access modifiers from code in this answer for clarity of demonstrating the essential point. Whether a constructor is accessible or not can also have a bearing on all this, but I deemed it out of scope
Looking at this question got me wondering if something similar is possible using the dark reflection ways of C#.
Say I have this code:
public class Foo
{
public void FooPrint() // can't change this implementation
{
Console.Write("Foo");
}
}
public class Bar
{
public Foo foo = new Foo();
public Bar()
{
//do some reflection magic with member foo here ?
}
public void FooPrintRewritten()
{
Console.Write("Haha, only for Bar.foo.");
}
}
class Program
{
static void Main(string[] args)
{
Foo a = new Foo();
a.FooPrint(); // should still print "Foo"
Bar bar = new Bar();
bar.foo.FooPrint(); // should print "Haha, only for Bar.foo."
}
}
Is what I ask for in the inlined comments in any way possible? Is there a way to re-bind a method call to another method for only a specific variable?
Yes I know this is ridiculous, no this shouldn't ever be used in production code. This is for the sake of curiosity.
Other answers have suggested ways in which you can achieve what you want on a functional level, which is arguably the sane thing to do, but I'll tackle the question directly: can this be done changing no code in the question except the implementation of Bar.Bar(), keeping Bar.foo of type Foo and changing nothing about Foo?
The answer is no. You cannot change the method table for a single object, which is basically what you're asking for here. The method table is part of the type, not the instance. If an expression f is of type Foo, and FooPrint is a non-virtual method of Foo, then the call f.FooPrint() will always resolve to Foo.FooPrint. Even worse, the compiler might choose to inline the call since that's obviously a safe optimization*. Where are your dark reflection ways now?
The only way to achieve this is to convince the compiler that calls to Foo.FooPrint should be treated specially, taking the instance into consideration. There are a few ways of doing so:
Foo.FooPrint could be made a delegate. The targets of a delegate call are specific per instance of the delegate.
Foo.FooPrint could be made a virtual, abstract or interface method. All of these are resolved based on the runtime type of the instance. Simply derive a class from Foo and away you go.
Foo could inherit from MarshalByRefObject. An MBRO, as it's commonly called, is treated specially by the jitter since (as the name implies) calls may need to be marshalled back. In particular, if Foo was an MBRO, you could create a RealProxy for it that will cough up a transparent proxy that resembles a real, actual Foo in almost all ways, right down to GetType(), except that you get to choose how calls are actually handled.
All of these approaches are used by various mocking/interceptor/proxy libraries, all of them require some change to Foo. The only approaches that require no (textual) change to Foo are those that rewrite the IL involved, like PostSharp or Microsoft Fakes, but I'd consider that cheating for purposes of this question.
* Technically, the C# standard says nothing about either method tables or permissible ways of inlining since those are implementation details, but it does say that Foo.FooPrint is always resolved in only one way without considering the instance (except that it must not be null).
Actually, there is a case for this type of behaviour under SRP of SOLID if you needed to separate implementations to maintain the principle (depending on how strictly you are adhering to SOLID ofc).
It's called the Interceptor pattern and used by Mocking libraries such as Moq.
Have a look at the following article on the subject for a good example of how the pattern can be used: C#: Why Decorate When You Can Intercept
Here's another way of overriding (virtual) methods when you instantiate a class
class Program
{
static void Main(string[] args)
{
Foo a = new Foo();
a.FooPrint(); // should still print "Foo"
Bar bar = new Bar();
bar.foo.FooPrint(); // should print "Haha, only for Bar.foo."
Console.Read();
}
}
public class Foo
{
public Action FooPrint = () => Console.WriteLine("Foo");
}
public class Bar
{
public Foo foo = new Foo()
{
FooPrint = () => Console.WriteLine("Haha, only for Bar.foo.")
};
}
this post explains how to make an override right when you instantiate a class.
However, it uses Func which requires a method which contains a return type that isnt void, thats why you'll want to use Action instead, as explained here
What about this, with still the same usage:
public class Wrapper : Foo
{
public new void FooPrint()
{
Console.Write("Haha, only for Bar.foo.");
}
}
public class Bar
{
public Wrapper foo = new Wrapper();
}
I'm having a generic function that returns a new instance of a subclass of AnyListVM implemented basically like this:
public TListVM MakeListVM<TListVM>()
where TListVM : AnyListVM
{
TListVM listVM;
switch(typeof(TListVM).ToString())
{
case nameof(EventListVM):
listVM = new EventListVM();
// some more init stuff
break;
// some more similar cases
default:
throw new NotImplementedException();
}
return listVM;
}
The two involved classes look currently like that, without any meaningful implementation yet:
public abstract class AnyListVM
{
}
public class EventListVM : AnyListVM
{
}
Now Visual Studio underlines my new EventListVM() and nags that it can't implicitly convert EventListVM to TListVM.
Okay, so I thought I simply add an explicit cast:
listVM = (TListVM)new EventListVM();
But nope. Now Visual Studio underlines it again and says that it's a redundant cast. The offered automatic fix would be to remove the cast again. Infinite loop.
What is going wrong here, why am I not allowed to do this cast, explicitly or implicitly?
There's one glaring thing in your implementation that is incorrect, which other's have pointed out but haven't addressed satisfactorily. If you intend to instantiate TListVM, then you need to change two very important parts. First the new code listing:
public TListVM MakeListVM<TListVM>()
where TListVM : AnyListVM, new()
{
TListVM listVM = new TListVM();
EventListVM evtList = listVM as EventListVM;
if (evtList != null)
{
// set evtList properties. You can't change
// the instantiation method.
}
// repeat for other constructs.
return listVM;
}
Now, to expound a bit. The generic where clause needs to specify that you intend to create the TListVM with a parameterless constructor. To do that, you need to specify new() as a generic constraint.
This greatly simplifies your implementation which only knows there is something called TListVM that has a base class of AnyListVM and has a constructor with no parameters. There's no need for a complicated switch statement, or using the Activator.
Any time you are dealing with generics, work with your generic parameter directly.
Based on further information, the switch statement is still the wrong tool. Generics necessarily constrain how you work with your object. You can't change the constructor, but you can specialize how you set properties after the object is instantiated.
Above I changed the listing to show how to set those properties directly.
If, instead you were dead set on having different constructors, etc. then you would have to approach it differently. You would have to return the base class and not TListVM.
public AnyListVM MakeListVM<TListVM>()
where TListVM : AnyListVM
{
return MakeListVM(typeof(TListVM)) as TListVM;
}
private AnyListVM MakeListVM(Type listVM)
{
AnyListVM listVM;
switch(listVM.ToString())
{
case nameof(EventListVM):
listVM = new EventListVM();
// some more init stuff
break;
// some more similar cases
default:
throw new NotImplementedException();
}
return listVM;
}
The generic helper method lets you wrap your more generic factory method so it has the signature you want, without causing compile errors.
You can't guarantee that EventListVM will convert to TListVM as according to your generic restriction, one is allowed to pass ANY inherited class of AnyListVM, which may or may not be EventListVM. Example, if the caller of this method did this:
AnyListVM vm = MakeListVM<SomeOtherListVMConcrete>();
It would fail, but shouldn't.
I believe what you really want is to cast your EventListVM to AnyListVM, the actual base type rather than the generic.
AnyListVM listVM = new EventListVM();
Still, if you are always returning an instance of EventListVM, I'd consider removing the generic clause all together and updating the signature to have a return type of EventListVM.
To make your problem more obvious, consider a base class and two children:
public class Base { } //AnyListVM
public class Child1 : Base{ } //EventListVM
public class Child2 : Base{ } //OtherListVM
now your method looks like:
public T Get<T>() where T : Base
{
//code
T item = new Child1();
//more code
}
Imagine I send in Child2, which is perfectly valid from the method signature. The method's code now looks like:
Child2 item = new Child1();
which of course is going to be invalid at compile time.
Why am I not allowed to have a static and non-static methods with the same signature?
Let's say I have a class like this
public class TestClass
{
public object thing { get; set; }
public TestClass()
{
}
public TestClass(object thing)
{
this.thing = thing;
}
public static TestClass ConvertTestClass(object thing)
{
return new TestClass(thing);
}
public TestClass ConvertTestClass(object thing)
{
this.thing = thing;
return this;
}
}
and I try to use it like this
public class SomeOtherClass
{
public SomeOtherClass()
{
TestClass tc = TestClass.ConvertTestClass(new object());
TestClass tc2 = new TestClass();
tc2.ConvertTestClass(new object());
}
}
I get the following errors on TestClass.ConvertTestClass(new object());
The call is ambiguous between the following methods or properties: 'TestClass.ConvertTestClass(object)' and 'TestClass.ConvertTestClass(object)'
and these errors on tc2.ConvertTestClass(new object());
The call is ambiguous between the following methods or properties: 'TestClass.ConvertTestClass(object)' and 'TestClass.ConvertTestClass(object)'
Member 'TestClass.ConvertTestClass(object)' cannot be accessed with an instance reference; qualify it with a type name instead
Can the compiler really not tell the difference between the static and non static versions of that method or am I missing something here?
I am not using ReSharper (which seemed to be the root of a similar problem in other questions).
Its giving you an error, so its a safe bet that the compiler can't, or won't, discern between the two methods.
Its probably a bad idea to do this kind of overload anyways, as it's unclear which method you are intending to invoke, but if that isn't enough, the C# 5 specification defines a method signature like this (Section 3.6):
The signature of a method consists of the name of the method, the
number of type parameters and the type and kind (value, reference, or
output) of each of its formal parameters, considered in the order left
to right. For these purposes, any type parameter of the method that
occurs in the type of a formal parameter is identified not by its
name, but by its ordinal position in the type argument list of the
method. The signature of a method specifically does not include the
return type, the params modifier that may be specified for the
right-most parameter, nor the optional type parameter constraints.
It doesn't explicitly mention static, but it also doesn't include it as part of the definition of a "signature". Thus, its fair to assume that by the spec, a method overload cannot differ only in the fact that it is static or instanced.
I'd write this as a comment however it's easier to make this point in a proper editor.
I think you're only thinking about the logic of calling methods on the class externally i.e. from another class. Within the class methods with the same signature only differing by static doesn't make any sense. e.g you have a class with two methods as follows
public class MyClass
{
public static void HellowWorld()
{
Console.WriteLine("Hello World!");
}
public void HellowWorld()
{
Console.WriteLine("Howdy World!");
}
public void Greet()
{
HellowWorld();
}
}
When compiling you'll see as long as one of the methods is commented out it compiles without errors. You should be able to alternate the commented out method and compile the class succesfully. Indicating there's no way of differentiating which method should be called within the scope of the class.
You could argue that within the class you should be forced to use the same syntax to call a static method as you do externally e.g.
MyClass.HelloWorld();
However, this would defy scoping logic used throughout C#, why should you need to specify the class name within a class? I think such a change would also create ambiguity where the was none, and to do so now would of course break a lot of code out there.
I think the compiler logic as it is makes perfect sense.
public Butler(IWeapon weapon): this(weapon, new Communicate())
{}
What does this(weapon, new Communicate()) mean?
It calls another constructor on the same type, passing in the weapon that was passed to this constructor, and a new Communicate object. I assume there is also something like:
// might actually be private
public Butler(IWeapon weapon, Communicate communicate) {...}
This approach is useful by allowing you to have multiple constructors, but only put the code in the most complex one. All the other constructors just pass the arguments (or defaults, as necessary) to the chosen constructor.
The chained constructor gets invoked before the body of the constructor that has the : this(...)
It calls a constructor in the same class but with different parameters, for example:
public class Test
{
public Test() : this("Richard")
{
}
public Test(string name)
{
}
}
It means Butler extends an instance of the current class where the weapon object passed as the argument, and a new instance of the Communicate object are passed to the class constructor.
it is calling another constructor with the signature Butler(IWeapon, ICommunicate).