I am disassembling some C# applications and I am trying to reconstruct the source code. I am disassembling the application along with the required DLLs.I keep coming across this line base..ctor(); which gives me an error. The line occurs in some voids with in some subclasses of Stream and Exception.
Does anyone have any idea what the code should be? I am thinking the disassembler messed it up some how and it is clearly invalid code.
So does anyone know what it is meant to mean and how I can change the line so it works?
Here is the code of one of the subclasses that line occurs in:
[Guid("ebc25cf6-9120-4283-b972-0e5520d0000E")]
public class ZlibException : Exception
{
public ZlibException()
{
base..ctor();
return;
}
public ZlibException(string s)
{
base..ctor();
return;
}
}
It should be :
[Guid("ebc25cf6-9120-4283-b972-0e5520d0000E")]
public class ZlibException : Exception
{
public ZlibException() : base()
{
return;
}
public ZlibException(string s) : base()
{
return;
}
}
Which calls the constructor with that signature on the base implementation of this class.
But by default the .NET CLR calls the base, blank constructor for you, so you don't actually need the : base()
It's calling the base constructor, your decompiler is just showing it strangely. In IL, constructors are called .ctor for short, so when directly reading the IL, your decompiler is apparently confused and thinks this is just another method.
The actual code would look like:
public class ZlibException : Exception
{
public ZlibException() : base();
{
return;
}
public ZlibException(string s) : base();
{
return;
}
}
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
I am having a strange error in one of my solutions while attempting to use Activator.CreateInstance having changed the parameter for the .ctor on the type being created from a plain generic T to an IEnumerable. I have extracted enough code to a console app to test in isolation but it appears to work just fine.
Below is the extracted code that works in the console app -
class Program
{
static void Main(string[] args)
{
Notify(new List<MyBase> { new MyBase(), new MyBase() });
}
private static void Notify<T>(IEnumerable<T> changes) where T : IMy
{
var dtoType = changes.First().GetType();
var type = typeof(MyNotification<>).MakeGenericType(dtoType);
var notification = (IMyNotification)Activator.CreateInstance(type, new object[] { changes });
}
}
public interface IMy { }
public class MyBase : IMy { }
public interface IMyNotification { }
public interface IMyNotification<T> : IMyNotification where T : IMy
{
}
public class MyNotification<T> : IMyNotification<T> where T : IMy
{
public MyNotification(IEnumerable<T> mys) { }
}
Essentially this is the same code as is running in my original solution.
The error is a MissingMethodException, so it cannot find a matching .ctor.
Run out of ideas on what could be causing this, looking at the type information in the debugger for both solutions I cannot see any difference. All projects are cleaned and built with the solution.
edit
Hoping someone can point me in another direction to potentially solve this issue.
Thanks
edit
I have tried changing the .ctor to be of type 'object' and with that change Activator can create the type.
Just use new MyNotification<T>(changes) if it is what you need.
I have base class that contain abstract method.
public abstract class ClassBase : IClassBase
{
protected ClassBase()
{
//// some code
}
protected ClassBase(XmlNode settings)
: this()
{
}
protected abstract void Init(XmlNode settings);
}
public class Class_A : ClassBase
{
public Class_A(XmlNode settings)
: this(settings)
{
Init(settings);
}
protected override void Init(XmlNode settings)
{
}
}
Is it ok to call the Init method from Class_A constructor ?
I try to do it and its run ok - but when the constructor is running the virtual tables are not ready yet and the abstract method are not ready as far as i know.
It's unclear exactly what code you meant, as the code you've given doesn't compile for a couple of reasons. Most importantly, did you actually mean to call Init from ClassBase rather than from Class_A? If not, it seems pointless making Init abstract. This answer assumes you did meant that.
Is it ok to call the Init method from Class_A constructor ?
It's valid - but it's not usually a good idea.
It's not a matter of the "virtual tables" no being created - that's fine, and it will execute Class_A.Init. An object is created as an instance of its eventual type immediately. The problem is that you're calling a method on the Class_A instance before its constructor has had a chance to execute. That means it may be in an unexpected state - normal preconditions may not hold, for example.
Example
public class Class_A : ClassBase
{
private readonly string text;
public Class_A(XmlNode settings, string text)
: base(settings) // Which calls Init(settings) as per intro paragraph
{
if (text == null)
{
throw new ArgumentNullException("text");
}
this.text = text;
}
protected override void Init(XmlNode settings)
{
// In here, text is still null... even though it can't be in any
// other method.
}
}
Just occasionally, it's the least worst solution, but in that case:
Really make sure there isn't a better solution
Document it very clearly
Avoid calling the method from anywhere else, as it's often odd to code an implementation which is appropriate in both "I'm half way through initialization" and "I'm fully initialized" states.
https://github.com/apache/log4net
I am compiling log4net from the source above, but it doesn't pass verification:
[IL]: Error: [log4net.dll : log4net.Plugin.RemoteLoggingServerPlugin::Attach][offset 0x00000029] Method is not visible.
Code is ok:
public interface ILoggerRepository
{
...
}
public interface IPlugin
{
void Attach(ILoggerRepository repository);
}
public abstract class PluginSkeleton : IPlugin
{
public virtual void Attach(ILoggerRepository repository) { }
}
public class RemoteLoggingServerPlugin : PluginSkeleton
{
override public void Attach(ILoggerRepository repository)
{
base.Attach(repository);
...
}
}
https://github.com/apache/log4net/blob/trunk/src/Plugin/IPlugin.cs
https://github.com/apache/log4net/blob/trunk/src/Plugin/PluginSkeleton.cs
https://github.com/apache/log4net/blob/trunk/src/Plugin/RemoteLoggingServerPlugin.cs
Investigation shows that it fails in calling RemotingServices.Marshal():
override public void Attach(ILoggerRepository repository)
{
base.Attach(repository);
// Create the sink and marshal it
m_sink = new RemoteLoggingSinkImpl(repository);
try
{
**RemotingServices.Marshal(m_sink, m_sinkUri, typeof(IRemoteLoggingSink));**
}
catch(Exception ex)
{
LogLog.Error(declaringType, "Failed to Marshal remoting sink", ex);
}
}
But there is nothing crucial here. Moreover calling RemotingServices.Marshal() with any type leads to the same problems:
Even if I change the Attach() to this:
override public void Attach(ILoggerRepository repository)
{
RemotingServices.Marshal(null, null, typeof(int));
}
Can someone spot what is the problem?
The problem is related to the fact that with .NET 4 Level 2 transparency was introduced. (See http://msdn.microsoft.com/en-us/library/dd233102.aspx for details.)
The method override public void Attach(ILoggerRepository repository) is lacking the SecuritySafeCriticalAttribute. Adding the attribute:
#if NET_4_0
[System.Security.SecuritySafeCritical]
#endif
override public void Attach(ILoggerRepository repository)
{
// ...
}
will make the IL verification pass. (Also see: http://msdn.microsoft.com/en-us/library/bb397858.aspx for further information.)
Update: To shed some more light on why verification fails (which might not be immediately clear by just reading the articles in the links provided) here is a short explanation.
RemotingServices.Marshal has the [SecuritySafeCritical] attribute applied. So one would assume that calling the method from a transparent method would be allowed. However RemotingServices.Marshal returns an object of type System.Runtime.Remoting.ObjRef and said type is annotated with the [SecurityCritical] attribute. If the log4net code would store a reference to the returned value in a local variable, Code Analysis would detect the error and issue a CA2140 warning ("Transparent code must not reference security critical items").
Now apparently under the security transparency rules, a transparent method may not call a security safe-critical method if the called method returns a security critical type even if the transparent method does not store a reference to the returned object as the following sample demonstrates:
public class TransparencyRulesDemo
{
[SecuritySafeCritical]
public void SafeGetCritical()
{
GetCritical();
}
public void TransparentGetCritical()
{
// Below line will trigger a CA2140 warning if uncommented...
// var critical = GetCritical();
// ...the following line on the other hand will not produce any warning
// but will lead to IL verification errors and MethodAccessExceptions if
// called from transparent code.
GetCritical();
}
[SecuritySafeCritical]
public Critical GetCritical()
{
return new Critical();
}
}
[SecurityCritical]
public class Critical
{
}
This btw. makes the [SecuritySafeCritical] attribute on RemotingServices.Marshal kind of pointless.
I'm trying to have an overloaded constructor for a class. I think this should be fairly simple, however I can't seem to make it work.
Any ideas?
public SaveFile(string location)
{
// Constructor logic here
//TODO: Implement save event.
this.Save(location);
}
public SaveFile()
{
string location = Environment.GetFolderPath(Environment.SpecialFolder.Personal) + "\\SaveFile.DAT";
SaveFile(location);
}
This doesn't compile correctly, and I can't figure out how to do make it work.
You have the wrong syntax for calling an overloaded constructor from within the default constructor.
To call an overloaded constructor in the same class, use this syntax:
public ClassName(parameters) : this(otherParameters)
{
// logic
}
If you wanted to call a constructor in the base class, then you would use the base keyword instead of this. In your case the code would read:
public SaveFile() : this(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Personal), "SaveFile.DAT") {}
public SaveFile(string location)
{
this.Save(location);
}
public SaveFile()
: this(Environment.GetFolderPath(Environment.SpecialFolder.Personal) + "\\SaveFile.DAT")
{
}
However that really should be:
public SaveFile()
: this(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Personal),"SaveFile.DAT"))
{
}
Try this
public SaveFile(string location)
{
// Constructor logic here
//TODO: Implement save event.
this.Save(location);
}
public SaveFile(): this(Environment.GetFolderPath(Environment.SpecialFolder.Personal) + "\\SaveFile.DAT")
{
}