I don't have too much knowledge of compilers and how .Net optimizes the generated machine code but would like to understand the following scenario:
class AnyClass
{
public bool anyFlag;
AnyClass()
{
anyFlag = true;
}
public void Action()
{
if(anyFlag)
//Perform Certain Actions
}
}
anyFlag does not change throughout the scope of the program. Will the compiler generate MIL/machine code for Action method? If so will it have the if check in there?
In your case the compiler won't filter the if statement because your anyFlag is public (so it can be changed from multiple places) and because the value is only is set in the consctructor the compiler also doesn't now this value until runtime.
The following code does what you want:
static void MyFunc()
{
const bool flag = true;
string s = null;
if (flag)
{
s = "a";
}
else
{
s = "b";
}
}
If you insert this code in Visual Studio you will see a generated warning stating that s="b"; will never be reached and this code will be optimized out.
Yes, the compiler will generate the IL. Since you could later user reflection or Emit to call that method or alter the value of anyFlag, it retains it. You can show this by disassembling the produced executable file using ildasm, which comes with Visual Studio.
Related
According to this answer when code uses local variables from inside lambda methods the compiler will generate extra classes that can have name such as c__DisplayClass1. For example the following (completely useless) code:
class Program
{
static void Main()
{
try {
implMain();
} catch (Exception e) {
Console.WriteLine(e.ToString());
}
}
static void implMain()
{
for (int i = 0; i < 10; i++) {
invoke(() => {
Console.WriteLine(i);
throw new InvalidOperationException();
});
}
}
static void invoke(Action what)
{
what();
}
}
outputs the following call stack:
System.InvalidOperationException
at ConsoleApplication1.Program.<>c__DisplayClass2.<implMain>b__0()
at ConsoleApplication1.Program.invoke(Action what)
at ConsoleApplication1.Program.implMain()
at ConsoleApplication1.Program.Main()
Note that there's c__DisplayClass2 in there which is a name of a class generated by the compiler to hold the loop variable.
According to this answer c__DisplayClass "means"
c --> anonymous method closure class ("DisplayClass")
Okay, but what does "DisplayClass" mean here?
What does this generated class "display"? In other words why is it not "MagicClass" or "GeneratedClass" or any other name?
From an answer to a related question by Eric Lippert:
The reason that a closure class is called "DisplayClass" is a bit unfortunate: this is jargon used by the debugger team to describe a class that has special behaviours when displayed in the debugger. Obviously we do not want to display "x" as a field of an impossibly-named class when you are debugging your code; rather, you want it to look like any other local variable. There is special gear in the debugger to handle doing so for this kind of display class. It probably should have been called "ClosureClass" instead, to make it easier to read disassembly.
You can get some insight from the C# compiler source as available from the SSCLI20 distribution, csharp/sccomp subdirectory. Searching the code for "display" gives most hits in the fncbind.cpp source code file. You'll see it used in code symbols as well as comments.
The comments strongly suggest that this was a term used internally by the team, possibly as far back as the design meetings. This is .NET 2.0 vintage code, there was not a lot of code rewriting going on yet. Just iterators and anonymous methods, both implemented in very similar ways. The term "display class" is offset from "user class" in the comments, a clear hint that they used the term to denote auto-generated classes. No strong hint why "display" was favored, I suspect that it might have something to do with these classes being visible in the metadata of the assembly.
Based on Reflector, DisplayClass can be translated as CompilerGeneratedClass
[CompilerGenerated]
private sealed class <>c__DisplayClass16b
{
// Fields
public MainForm <>4__this;
public object sender;
// Methods
public void <cmdADSInit_Click>b__16a()
{
ADS.Initialize();
this.<>4__this._Sender = this.sender;
this.<>4__this.SelectedObject = ADS.Instance;
}
}
My understanding is that the "Access to modified closure" warning is there to warn me about accessing local variables from a delegate when the delegate might be stored and called later or called on a different thread so that the local variable isn't actually available at the time of actual code execution. This is sensible of course.
But what if I am creating a delegate that I know is going to be called immediately in the same thread? The warning then is not needed. For example the warning is generated in the code:
delegate void Consume();
private void ConsumeConsume(Consume c)
{
c();
}
public int Hello()
{
int a = 0;
ConsumeConsume(() => { a += 9; });
a = 1;
return a;
}
There can be no problem here since ConsumeConsume always calls the function immediately. Is there any way around this? Is there some way to annotate the function ConsumeConsume to indicate the ReSharper that the delegate will be called immediately?
Interestingly, when I replace the ConsumeConsume(() => { a += 9; }); line with:
new List<int>(new[] {1}).ForEach(i => { a += 9; });
which does the same thing, no warning is generated. Is this just an in-built exception for ReSharper or is there something I can do similarly to indicate that the delegate is called immediately?
I am aware that I can disable these warnings but that is not a desired outcome.
Install the JetBrains.Annotations package with NuGet: https://www.nuget.org/packages/JetBrains.Annotations
Mark the passed in delegate with the InstantHandle attribute.
private void ConsumeConsume([InstantHandle] Consume c)
{
c();
}
From InstantHandle's description:
Tells code analysis engine if the parameter is completely handled when the invoked method is on stack. If the parameter is a delegate, indicates that delegate is executed while the method is executed. If the parameter is an enumerable, indicates that it is enumerated while the method is executed.
Source: https://www.jetbrains.com/help/resharper/Reference__Code_Annotation_Attributes.html
If you don't want to add the whole package to your project, it's enough to just add the attribute yourself, although it's hacky in my opinion.
namespace JetBrains.Annotations
{
[AttributeUsage(AttributeTargets.Parameter)]
public class InstantHandleAttribute : Attribute { }
}
Here is my code:
public class UserPreferences
{
/// <summary>
/// The EMail signature.
/// </summary>
[UserPreferenceProperty(Category = "Email", DefaultValue = "My default value")]
public static string Signature
{
get
{
return UserPreferenceManager.GetValue();
}
set
{
UserPreferenceManager.SetValue(value);
}
}
}
public static string GetValue()
{
if (((VTXPrincipal)Thread.CurrentPrincipal).VTXIdentity.OperatorID == null)
{
throw new Exception("Missing Operator ID");
}
string value = string.Empty;
var frame = new StackFrame(1); ***** <------ problem here.....
var property = frame.GetMethod();
var propertyname = property.Name.Split('_')[1];
var type = property.DeclaringType; ***** <------ problem here.....
if (type != null)
{
var userPreference = typeof(UserPreferences).GetProperty(propertyname).GetCustomAttributes(true).FirstOrDefault() as UserPreferencePropertyAttribute;
if (userPreference != null)
{
string category = userPreference.Category;
string description = propertyname;
value = GetValue(category, description, ((VTXPrincipal)Thread.CurrentPrincipal).VTXIdentity.OperatorID);
if (value == null)
{
// always return something
return userPreference.DefaultValue;
}
}
else
{
throw new Exception("Missing User Preference");
}
}
return value;
}
Inside the GetValue method, StackFrame works differently in release mode vs. debug mode.
In debug mode, I correctly get the property name as signature
But in Release mode, property name is GetUserPreferenceValueTest because this is the test method that makes the calls as clients.
There fore my code works in debug mode but fails in release mode.
Q. How can I use StackFrame properly so it works in Debug vs. Release modes.
Q. Is there any other way to get calling property name and related information at run time?
I answered a similar question once, please read my answer here.
In short, this is a very bad design decision because your method is a hypocrite—it talks different to different callers but doesn't tell it in open. Your API should never, ever rely on who calls it. Also, the compiler can break the stack trace in an unexpected way due to language features like lambdas, yield and await, so even if this worked in Release mode, it would certainly break some day.
You're effectively building a complex indirection mechanism instead of using language feature designed for passing information to methods—method parameters.
Why do you use attributes? Do you read them elsewhere?
If you do, and you don't want to repeat "Email" both as parameter to GetValue call and attribute value, you may consider passing a property Expression<> to GetValue, which will extract the attribute. This is similar to your solution, but it is explicit:
[UserPreferenceProperty(Category = "Email", DefaultValue = "My default value")]
public string Signature
{
get { return GetValue (prefs => prefs.Signature); }
set { SetValue (prefs => prefs.Signature, value); }
}
This answer shows how to implement this.
I see you are checking Thread.CurrentPrincipal in your code. Again, this is not a really good practice because it is not obvious to client code that accessing a property can result in an exception. This is going to be a debugging nightmare for someone who supports your code (and trust me, your code may run for years in production, long after you move onto another project).
Instead, you should make VTXIdentity a parameter to your settings class constructor. This will ensure the calling code knows you enforce security on this level and by definition knows where to obtain this token. Also, this allows you to throw an exception as soon as you know something is wrong, rather than when accessing some property. This will help maintainers catch errors earlier—much like compile errors are better than runtime errors.
Finally, while this is a fun exercise, there are plenty performant and tested solutions for storing and reading configuration in C#. Why do you think you need to reinvent the wheel?
Assuming your problem survives the discussion of whether you could just use another library rather than rolling your own... if you find yourself using C# 5 &.NET 4.5, take a look at the CallerMemberName attribute. With CallerMemberName you can modify your GetValue() method signature to be
public static string GetValue([CallerMemberName] string callerName = "")
The property can then call GetValue() with no parameter and you'll get the property name passed into GetValue() as you want.
I'm using a very simple ternary expression in my C# code:
helperClass.SomeData = helperClass.HasData ? GetSomeData() : GetSomeOtherData();
In both cases, the functions on each path of the expression return a non-null object, but if I look at the result in the debugger, it is null until I reference it in the code such as using an assert:
Debug.Assert(helperClass.SomeData != null);
This only appears to happen if I use an "x64" or "Any CPU" platform setting in Debug mode. It's fine in "x86" mode.
I try to be very cautious before assuming I've found a bug in the compiler or debugger, but I can't find any other explanation for this behavior.
Here's a full class to do a repro, just call SomeClass.SomeAction() in the debugger in x64 mode and step through to see it:
public class SomeClass {
public bool HasData;
public object SomeData;
private SomeClass() {
HasData = false;
}
public static void SomeAction() {
var helperClass = new SomeClass();
// Exhibits weird debugger behavior of having helperClass.SomeData = null after this line:
helperClass.SomeData = helperClass.HasData ? GetSomeData() : GetSomeOtherData();
// Note that trying helperClass.SomeData.ToString() returns a debugger error saying SomeData is null
// But this code is just fine
//if(helperClass.HasData) {
// helperClass.SomeData = GetSomeData();
//}
//else {
// helperClass.SomeData = GetSomeOtherData();
//}
// In both cases though, after this line things are fine:
Debug.Assert(helperClass.SomeData != null);
}
private static object GetSomeData() {
return new object();
}
private static object GetSomeOtherData() {
return new object();
}
}
Am I missing something or is this a bug in the x64 debugger? I'm using debug mode so no optimizations should be present.
Taking Eric Lippert's advice that this is probably a bug, I've filed an official Connect bug for this issue: https://connect.microsoft.com/VisualStudio/feedback/details/684202
Thanks everyone for your feedback!
UPDATE: They got back to me and said they've fixed this corner case in the next version of the compiler. Hooray! :)
to me this doesn't seem a bug in the debugger but possibly of the compiler...
when changing the code to
{ helperClass.SomeData = helperClass.HasData ? GetSomeData() : GetSomeOtherData(); }
the IL generated is different and the debugger works as expected...
I'd like to list all the methods that are called from a specific method. E.g. if I have the following code:
public void test1() {
test2();
test3();
}
The list should contain test2() and test3(). It would be great if methods of the same class but also methods of another class could be listed.
Additionaly I'd like to find a way to detect which fields are used of a method:
public class A {
private String test1 = "";
private String test2 = "";
public void test() {
Console.WriteLine(test1);
}
}
Should therefore list test1.
I tried this using Mono.Cecil, but unfortunately I couldn't find lot of documentation about the project. So does anybody know how to do that?
Edit: I'd like to do it with Mono.Cecil because over its API I can directly use the results in my application. If I use built in tools in Visual Studio or similar, it's quite difficult to furhter process the results.
I haven't really worked with Cecil but the HowTo page shows how to enumerate the types, your problem only seems to require looping over the instructions for the ones your after: Call and Load Field. This sample code seems to handle the cases you mentioned but there may be more to it, you should probably check the other Call instructions too. If you make it recursive make sure you keep track of the methods you've already checked.
static void Main(string[] args)
{
var module = ModuleDefinition.ReadModule("CecilTest.exe");
var type = module.Types.First(x => x.Name == "A");
var method = type.Methods.First(x => x.Name == "test");
PrintMethods(method);
PrintFields(method);
Console.ReadLine();
}
public static void PrintMethods(MethodDefinition method)
{
Console.WriteLine(method.Name);
foreach (var instruction in method.Body.Instructions)
{
if (instruction.OpCode == OpCodes.Call)
{
MethodReference methodCall = instruction.Operand as MethodReference;
if(methodCall != null)
Console.WriteLine("\t" + methodCall.Name);
}
}
}
public static void PrintFields(MethodDefinition method)
{
Console.WriteLine(method.Name);
foreach (var instruction in method.Body.Instructions)
{
if (instruction.OpCode == OpCodes.Ldfld)
{
FieldReference field = instruction.Operand as FieldReference;
if (field != null)
Console.WriteLine("\t" + field.Name);
}
}
}
This can't be done simply using the reflection API within C#. Really you would need to parse the original source code which is probably not the kind of solution you're looking for. But for example this is how Visual Studio gets this kind of info to do refactoring.
You might get somewhere analysing the IL - along the lines of what Reflector does but that would be a huge piece of work I think.
you can use .NET Reflector tool if you want to pay. you could also take a look at this .NET Method Dependencies it gets tricky though, as you're going to be going into the IL. A third possible would be to use the macro engine in VS, it does have a facility to analyze code,CodeElement, I'm not sure if it can do dependencies though.