Decompiling leads to error CS1112, assembly confusion - c#

So I ran a C# university program through de4dot and then reflector to decompile it and the following error appeared when I ran it in VS.
[assembly: System.Runtime.CompilerServices.Extension]
Error CS1112 Do not use
'System.Runtime.CompilerServices.ExtensionAttribute'. Use the 'this'
keyword
instead. Client C:\Users\user\Desktop\333\as2\decom\AssemblyInfo.cs 15 Active
I tried replacing the code with this and this() among other things but that just causes other problems. Can someone explain what I am to replace with 'this'? I feel like I am missing something obvious here.

The [assembly: Extension] attribute is added to an assembly by the compiler when the assembly contains extension methods. This happens automatically, and based on the error you're seeing, the compiler doesn't want you doing it explicitly. Assuming the rest of the decompiler output is correct, comment out the assembly-level attribute, and you should be fine.
That said, you should never assume that a decompiler's output is correct.

You're meant to add the this modifier to the method:
public static class FooExtensions
{
public static void DoSomething(this Foo foo)
{
...
}
}
That makes it an extension method.
In general thought, I wouldn't try to use a decompiler to "round trip" code - decompilers can be useful to see what the compiler has actually done, but there are various situations where the result won't be compilable.

Related

What does the syntax seen when decompiling c# dynamic operations actually mean?

I've recently had to make a forray into decompiling a colleague's code while they're away, and found that most of it looks surprisingly nice (thanks ILSpy), with the notable exception of a couple of places where we needed to use dynamic - these got mangled into several parts:
A call site container - i.e. what resembles a class in definition, but let's say the method in which dynamic was used was DoStuff, would have a declaration along the lines of public /* static? I forget */ class <DoStuff>CallSiteContainer_Plus_Some_Weirdness { /* bunch of CallSite fields */ }
A lot of code that checks whether various CallSites within the container have been assigned and assigns them before usage as required using approaches I really don't get yet.
My question is regarding the syntax of the class declaration in the 1st point. It looks like a generic class, but it clearly isn't. Can anyone explain what's going on there?
Please note, I'm not looking for help in working out the original code - I've already managed to do that by judicious use of find and replace, and breaking out the autogenerated code from everything else. But I'd like to understand how the CallSite container syntax is a valid class name!
Here's an example of such auto-generated class:
private static class <>o__0
{
public static CallSite<Action<CallSite, Type, object>> <>p__0;
}
If you are worried about the <>o__0 class name and the <>p__0 field name, then you are right, those are not valid C# names but this doesn't mean that they are not valid IL names which is what the compiler generates. The reason why it uses such special symbols is to ensure that they will never conflict with class names that you as a developer might have written.

How to Move a class to another dll and change the namespace without altering the method usage

I have a dll where I have one class which logs to a "channel", another Program listens to the "channel" and writes the logs to the screen.
The problem with the dll is that its grown over time and now there are many dependecies in it. I want to remove the logging part from this dll and place it in a debugging and logging dll.
The problem is that the debugging and logging dll has another namespace which I want to use in the class or rather I want to use the class in the namespace. My problem with this is that some developers used the namespace nearly exclusively when calling the methods instead of using it in the top of their classes.
It looks like the following for a static method:
Base.Manager.Logging.Send("Log something");
The other Dll has the simple namespace Trace
so it should look like this:
Trace.Logging.Send("Log something");
My question is, is there an elegant way to move the class and change the namespace without altering all the uses of the Methods ?
I could simply copy the class to the other dll and then use the old class as a wrapper which forwards all the calls to the other class in the Trace.dll but this approach seems a little bit hacky.
I hope this grafik illustrates what I mean because I think the simple text may be somewhat confusing
FYI: I don't have ReSharper
Unfortunately you can't. If you keep same namespace then you can use TypeForwardAttribute but if you also change namespace (not just assembly) then it doesn't work.
What I suggest is to move it to new class, keep old class to don't break code both at run-time & compile-time and forward all calls. Mark all old methods as obsolete (at least they'll be warned that code will change in future). Just to clarify:
namespace Base.Manager {
public static class Logger {
public static void Send(string message) {
// Do things
}
}
Step 1: empty your old deprecated class and forward calls to new class. Mark old methods as obsolete.
Will then be refactored to:
namespace Base.Manager {
[EditorBrowsable(EditorBrowsableState.Never)]
public static class Logger {
[Obsolete("This method is deprecated, please use Trace.Logger.Send")]
public static void Send(string message) {
// Delegate work to someone else...
Trace.Logger.Send(message);
}
}
It'll generate a warning (with given message) during compilation. Compile-time compatibility is saved. Note we also added EditorBrowsableAttribute, IntelliSense won't propose that Logger class when they start typing. This reduces (little bit) chances they will still use Base.Manager.Logger for new code.
Step 2: someday in future you'll change that warning to an error:
[Obsolete("This method is obsolete, use Trace.Logger.Send", true)]
This will break compilation but it'll preserve binaries compatibility. Other DLLs will still run (so you don't have to wait other developers complete this refactoring task) but they won't be able to compile unless they update.
Step 3: when all has been done and everyone moved to new class then simply remove Base.Manager.Logger class from your code.
Notes: that all process can be spanned across various releases: in 2.0 you deprecate old methods, in 2.1 you break compilation, in 3.0 you remove it from your code (this is especially useful if releases of your code and its users aren't in sync).
Just a word about name collisions: be aware that same class name (and methods) in two different namespace may lead to annoying name collisions. Imagine they have this code:
using Base.Manager;
void DoSomething() {
Logger.Send("I'm doing something.");
}
After your change (until Base.Manager.Logger isn't removed) they can't simply add another using:
using Base.Manager;
using Trace;
void DoSomething() {
Base.Manager.SomethingElse.DoIt();
// Compiler is confused: Base.Manager.Logger or Trace.Logger?
Logger.Send("I'm doing something.");
}
They need to full qualify which logger class they want to use:
Trace.Logger.Send("I'm doing something.");
Warning: be aware that if Trace isn't a new namespace then name collision may even break compilation immediately if they had both usings in their code (making ObsoleteAttribute useless).
If it's an issue or not for you/your users...I can't say.

Constructor with no definition

I'm new to .Net and I just saw this code that doesn't make sense to me (slightly abridged):
namespace test
{
public class sub : super
{
public sub(string text);
}
}
As you can see, there is a constructor that takes an argument, but does not implement a definition. How does that work? My guess is that it somehow relates to the super class, but I dont understand how, and I havent been able to find anything on Google.
Edit: Im running this in VS2010, and I just noticed that the tab has [from metadata] in the title. Perhaps this is why?
That's not code.
That's text that looks somewhat like code based on the metadata in the assembly. You'll see this when the IDE doesn't have access to the source code in question (For example, you press F12 on a method in a referenced assembly.) It provides the method signatures, properties, fields, etc from the types, without providing any of the actual implementation.
As written, the code you posted wouldn't even compile in C#.
If from the metadata, it's not going to show you the implementation of the methods.
It looks like code but it is text based on the metadata in the assembly. It means that the IDE is unable to access the source code in question.

Conditional DEBUG - Does it still compile into RELEASE code?

I know that if I mark code as DEBUG code it won't run in RELEASE mode, but does it still get compiled into an assembly? I just wanna make sure my assembly isn't bloated by extra methods.
[Conditional(DEBUG)]
private void DoSomeLocalDebugging()
{
//debugging
}
Yes, the method itself still is built however you compile.
This is entirely logical - because the point of Conditional is to depend on the preprocessor symbols defined when the caller is built, not when the callee is built.
Simple test - build this:
using System;
using System.Diagnostics;
class Test
{
[Conditional("FOO")]
static void CallMe()
{
Console.WriteLine("Called");
}
static void Main()
{
CallMe();
}
}
Run the code (without defining FOO) and you'll see there's no output, but if you look in Reflector you'll see the method is still there.
To put it another way: do you think the .NET released assemblies (the ones we compile against) are built with the DEBUG symbol defined? If they're not (and I strongly suspect they're not!) how would we be able to call Debug.Assert etc?
Admittedly when you're building private methods it would make sense not to include it - but as you can see, it still is built - which is reasonable for simplicity and consistency.

C# Extension methods in .NET 2.0

I have found several links to methods of making extension methods work in .NET2.0 (The moth, Discord & Rhyme, Stack Overflow). I have also heard vaguely from a colleague that this causes some problems with libraries or something? Is this the case? Also all 3 use different methods:
The moth:
namespace System.Runtime.CompilerServices
{
public class ExtensionAttribute : Attribute { }
}
Discord and Rhyme
namespace System.Runtime.CompilerServices
{
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)]
public class ExtensionAttribute : Attribute {}
}
Stack Overflow
namespace System.Runtime.CompilerServices
{
[AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Class
| AttributeTargets.Method)]
public sealed class ExtensionAttribute : Attribute {}
}
Whats the difference between these methods, and which one would you recommend?
Ultimately it isn't going to make much difference; you could argue that the one that matches the runtime is preferred, but the ideal answer is to switch to .NET 3.5 (otherwise at a later date it can get confusing with different versions of the same attribute in scope etc).
The [AttributeUsage] will prevent it being attached to things where it won't do anything - but it won't do aything by itself anyway...
Looking at metadata against the type, the exact attribute usage seems most like the stackoverflow variant - but ultimately this isn't hugely important - the name and namespace is all that matters (and that it inherits from Attribute).
The difference is simple enough:
In your first example, you can put the attribute anywhere. In the second example, you can only apply it to a method, never more than one to the same method and an inherited class with the method overridden will not inherit the attribute. In the third example, you can apply it to a method, a class or an assembly.
If you try to apply it in any other place, you will get a compiler error.
The second seems to make most sense.
I would recommend Discord and Rhyme because it providing meaningful constraints for how the attribute is supposed to be applied.
It can only be applied to methods
You can only apply it once
The attribute cannot be inherited
Personally, I would recommend avoiding all three. Each option makes this work by performing a "trick" - I would not rely on this for production code.
If you want to use extension methods, upgrade to C# 3.0. Otherwise, just stick to calling the method using the non-extension method syntax.
You can always take an extension method call like so:
public static class Utility {
public static string Extension(this string original) { ... }
// call with:
var newString = myString.Extension();
And call it directly:
string newString = Utility.Extension(myString);
This will be more consistent with C#/.NET 2 syntax, and would be my recommendation.
The SO version is the accurate one, for the pure sake of accuracy you should use it.
Fwiw, the AttributeTarget.Method specifier is crystal clear. Class and Assembly less so. Both the C# and the VB.NET compiler emit the attribute on the static class / Module that contains the extension method. And on the assembly that contains the class / Module. Why they do this is less crystal clear, it wouldn't be needed to properly compile them. I'm guessing this is an optimization at work, helping both the compiler and IntelliSense discover when an extension method should be considered.
Getting the attribute applied to the assembly is actually a problem. That won't work right when you compile code to .netmodules. But that's a very obscure issue.

Categories

Resources