I am trying to identify usages of the "method group" syntax in my solution. The reason is that Resharper tries to help with the ConvertClosureToMethodGroup code inspection. The problem is, that the "optimized" code does not compile to the same IL code, which means that it breaks in my specific scenario. The below scenario does not break, but it illustrates what I am trying to find:
void Main()
{
var arr = new string[]{"foo"};
//This works
var bar = arr.Select(s=>MyMethod(s));
//Resharper suggests the below, which is different
//var bar = arr.Select(MyMethod);
}
string MyMethod(string s)
{
return "bar";
}
So: Is there a way, that I can identify all the places in my code, where any method is being passed as a method group?
I can disable the refactoring suggestion to prevent future usages of this, but how can I identify the places where this already happened?
EDIT 1: Example where this refactoring breaks runtime
void Main()
{
MyClass obj = null;
//This works
var lazy = new Lazy<bool>(()=> obj.MyMethod());
//This will break at runtime when obj is null
//var lazy = new Lazy<bool>(obj.MyMethod);
}
class MyClass
{
public bool MyMethod()
{
return false;
}
}
Related
In code which regularly needs debug logging, I end up with large blocks of code such as:
int someVar = 1;
bool anotherVar = true;
//...
string lastVar = "foo";
// littered through the code
Log._Debug(
"arbitrary message string",
$"{nameof(someVar)} = {someVar} " +
$"{nameof(anotherVar)} = {anotherVar} " +
// ...
$"{nameof(lastVar)} = {lastVar} "
);
These debug blocks can sometimes be huge (20+ vars being logged) and they can occur dozens of times in a class making the whole thing completely unreadable. Sadly they're necessary - sometimes we need to send debug builds to users (they can't run debugger, it's easier just to get them to run the debug build and send us the logs). It's also old code base which is why it's such a freaking mess.
I'm trying to find a way to debloat the debug chunks in the code, just to make it less depressing to maintain lol.
In my quest to find cleaner syntax, I found https://stackoverflow.com/a/9801735 which shows how to get member name from a lambda function. Which made me wonder, is it possible to create something a bit like this...?
Log._Dump(
"arbitrary message string",
() => somevar,
() => anotherVar,
// ...
() => lastVar
);
So I tried creating a method using params as follows:
[Conditional("DEBUG")]
public static void _Dump(string message, params Func[] vars) {
// ^ what <T> do I use?
}
private static string GetMemberName<T>(Expression<Func<T>> memberExpression) {
// this would eventually return $"{memberName} = {memberValue}"
// which, btw, I have no idea if that's even possible yet
// but I didn't get that far as still trying to work out how to do
// the _Dump() method params above :/
MemberExpression expressionBody = (MemberExpression)memberExpression.Body;
return expressionBody.Member.Name;
}
I don't know how to do params array of functions with varying return types.
I could potentially just make the params a string array and do the GetMemberName manually for each lambda, for example:
private string NV<T>(Expression<Func<T>> memberExpression) {
// ...code...
return $"{memberName} = {memberValue}";
}
Log._Dump(
"arbitrary message string",
NV(() => somevar),
NV(() => anotherVar),
// ...
NV(() => lastVar)
);
But that's adding boilerplate to the code again which is what I'm trying to avoid. Is there any way I can get it working without that extra NV() wrapper?
EDIT: It's really old codebase and we're stuck with .Net Framework 3.5 so limited to C# 6 or something like that.
C# 10 introduced [CallerArgumentExpression] (docs), a way to pass a string representation of the callers source code. So you could write a helper method;
public void Log<T>(T value, [CallerArgumentExpression("value")] string name=null)
=> Log($"{name} = {value}");
But you could also combine this with another new feature, [InterpolatedStringHandler] (docs) to log the name of any variable inside an interpolated string.
[InterpolatedStringHandler]
public ref struct DebugLogHandler
{
private readonly StringBuilder sb;
public DebugLogHandler(int literalLen, int formattedCount)
{
sb = new StringBuilder(literalLen);
}
public void AppendLiteral(string s) => sb.Append(s);
public void AppendFormatted<T>(T value, [CallerArgumentExpression("value")] string name=null)
{
sb.Append(name);
sb.Append("=");
sb.Append(value?.ToString());
}
public string BuildMessage() => sb.ToString();
}
public static void Log(string message) { ...TODO... }
public static void Log(DebugLogHandler builder)
=> Log(builder.BuildMessage());
var variableName = "value";
Log($"Something {variableName}");
I've been trying to figure out how I could use the Maybe monad in iSynaptic.Commons in a context where my value retriever could throw an exception:
For example:
dynamic expando = new Expando();
expando.Name = "John Doe";
var maybe = Maybe.Defer(()=>(string)expando.NonExistingProperty);
//In this context I would like the exception which is thrown
//to result in Maybe<string>.NoValue;
if(maybe.HasValue) {
//Do something
}
Is this possible with the implementation of maybe that is out there
There are several ways of using iSynaptic.Commons to allow an exception. Each way I found requires the .Catch() extension method to let the monad know to silently catch the exception. Also, be careful when accessing the property maybe.Value. If this property is Maybe.NoValue, an InvalidOperationException will be thrown.
1) Create a "OnExceptionNoValue" extension method. This will check the Maybe to see if it has an exception. If it does, a NoValue Maybe will be returned. Otherwise the original Maybe will be returned.
public static class MaybeLocalExtensions
{
public static Maybe<T> OnExceptionNoValue<T>(this Maybe<T> maybe)
{
return maybe.Exception != null ? Maybe<T>.NoValue : maybe;
}
}
// Sample Use Case:
var maybe = Maybe.Defer(() => (string)expando.NonExistingProperty).Catch()
.OnExceptionNoValue();
2) Create a "BindCatch" extension method. This changes the behavior of the normal bind when an exception is present to return Maybe.NoValue instead of throwing an exception.
public static class MaybeLocalExtensions
{
public static Maybe<TResult> BindCatch<T, TResult>(this Maybe<T> #this, Func<T, Maybe<TResult>> selector)
{
var self = #this;
return new Maybe<TResult>(() => {
if (self.Exception != null)
return Maybe<TResult>.NoValue;
return self.HasValue ? selector(self.Value) : Maybe<TResult>.NoValue;
});
}
}
// Sample Use Case:
var maybe = Maybe.Defer(() => (string)expando.NonExistingProperty).Catch()
.BindCatch(m => m.ToMaybe());
3) This way also uses the Catch() extension method, but uses the maybe.HasValue property instead of relying on extension methods. If an exception is present in the Maybe, the HasValue property is false. When this value is false, the Maybe.NoValue can replace the value of the variable maybe or whatever needs to be done in this case.
dynamic expando = new ExpandoObject();
expando.Name = "John Doe";
// This example falls to the else block.
var maybe = Maybe.Defer(() => (string)expando.NonExistingProperty).Catch();
//In this context I would like the exception which is thrown
//to result in Maybe<string>.NoValue;
if (maybe.HasValue) {
//Do something
Console.WriteLine(maybe.Value);
} else {
maybe = Maybe<string>.NoValue; // This line is run
}
// This example uses the if block.
maybe = Maybe.Defer(() => (string)expando.Name).Catch();
//to result in Maybe<string>.NoValue;
if (maybe.HasValue) {
//Do something
Console.WriteLine(maybe.Value); //This line is run
} else {
maybe = Maybe<string>.NoValue;
}
These answers are all variations on the same theme, but I hope they are helpful.
So I encountered a strange issue today - I had a simple creation of an instance inside the critical section of a lock, and it would throw a null reference exception when I manually dragged the next line to execute. To illustrate:
public class SearchEngineOptimizationParser
{
protected static ConcurrentDictionary<string, SearchEngineOptimizationInfo> _referralInformation = null;
protected static DateTime _lastRecordingDate;
protected static object _lockRecordingObject = new object();
protected static Dictionary<string, string> _searchProviderLookups = null;
static SearchEngineOptimizationParser()
{
_referralInformation = new ConcurrentDictionary<string, SearchEngineOptimizationInfo>();
_lastRecordingDate = DateTime.Now;
_searchProviderLookups = new Dictionary<string, string>();
_searchProviderLookups.Add("google.com", "q");
_searchProviderLookups.Add("yahoo.com", "p");
_searchProviderLookups.Add("bing.com", "q");
}
public SearchEngineOptimizationParser()
{
}
public virtual void ParseReferrer(Uri requestUrl, NameValueCollection serverVariables, ISession session)
{
string corePath = requestUrl.PathAndQuery.SmartSplit('?')[0].ToLower();
string referrer = serverVariables["HTTP_REFERER"];
if (!string.IsNullOrWhiteSpace(referrer))
{
NameValueCollection queryString = HttpUtility.ParseQueryString(referrer);
string dictionaryKey = session.AffiliateID + "|" + corePath;
foreach (var searchProvider in _searchProviderLookups)
{
if (referrer.Contains(searchProvider.Key))
{
if (queryString[searchProvider.Value] != null)
{
string keywords = queryString[searchProvider.Value];
SearchEngineOptimizationInfo info = new SearchEngineOptimizationInfo
{
Count = 1,
CorePath = corePath,
AffiliateId = session.AffiliateID,
Keywords = keywords
};
_referralInformation.AddOrUpdate(dictionaryKey, info, (key, oldValue) =>
{
oldValue.Count++;
return oldValue;
});
break;
}
}
}
}
if (DateTime.Now > _lastRecordingDate.AddHours(1))
{
lock (_lockRecordingObject)
{
if (DateTime.Now > _lastRecordingDate.AddHours(1))
{
SearchEngineKeywordRepository repository = new SearchEngineKeywordRepository();
List<KeyValuePair<string, SearchEngineOptimizationInfo>> currentInfo = _referralInformation.ToList();
Action logData = () =>
{
foreach (var item in currentInfo)
repository.LogKeyword(item.Value);
};
Thread logThread = new Thread(new ThreadStart(logData));
logThread.Start();
_lastRecordingDate = DateTime.Now;
_referralInformation.Clear();
}
}
}
}
EDIT: Updated Real Object
public class SearchEngineKeywordRepository
{
public virtual void LogKeyword(SearchEngineOptimizationInfo keywordInfo)
{
LogSearchEngineKeywords procedure = new LogSearchEngineKeywords();
procedure.Execute(keywordInfo.CorePath, keywordInfo.AffiliateId, keywordInfo.Keywords, keywordInfo.Count);
}
}
The general pattern being that I want to do this 'something' only every hour (in the context of a website application that gets a lot of traffic). I would breakpoint my first if statement, and then step the next line to execute inside the second if statement. When doing so, the act of initializing the SomeObject instance would cause a null reference exception. It had a completely 100% default constructor - I didn't even specify one.
However, when I let the code go through naturally, it would execute without problem. For some reason, it seems that when I skipped over the lock call into the critical section to just test run that code, it caused all kinds of errors.
I'm curious to know why that is; I understand the lock keyword is just syntactic sugar for a Monitor.Enter(o) try / finally block, but that seems to be that when invoking the constructor, something else was happening.
Anyone have any ideas?
EDIT: I've added the actual code to this. I'm able to reproduce this at will, but I still don't understand why this is happening. I've tried copying this code to another solution and the problem does not seem to occur.
I've tried to reproduce your situation, but as I expected I could not. I've tried both the 2.0 and 4.0 runtime, in 32 and 64 bit mode (debugging sometimes behaves differently under x64).
Is the code shown a simplification? Have you checked all your assumptions? I understand you're skipping 3 lines of code, both the if statements and the lock? In that case, even setting the lock object to null does not cause the exception you describe.
(Having _lockRecordingObject set to null causes an ArgumentNullException when leaving the lock scope)
I can't explain an issue I've run across. Basically I get a different answer if I use lambda syntax in a foreach loop than if I use it in a for loop. In the code below I register a delegate in a "dispatcher" class. I then later wrap the delegate on the way out in another delegate and return a list of these wrapped delegates. I then execute them. The expected output of executing the wrapped function list is 1,2. However I don't see that when I combine a lambda and a foreach loop.
This is not the code that is causing the problem, but the simplest case I could make to reproduce it. I would prefer not to discuss use cases of this, I'm more curious as to why I get behavior I'm not expecting. If I use the foreach loop below with the lambda syntax it fails. If I use the new Action() syntax and a foreach it works, if I use the lambda syntax in a for loop it works. Can anyone explain what is going on here. This has me really stumped.
public class Holder
{
public Holder(int ID, Dispatcher disp)
{
this.ID = ID;
disp.Register(Something);
}
public int ID { get; set; }
private void Something(int test) { Console.WriteLine(ID.ToString()); }
}
public class Dispatcher
{
List<Action<int>> m_Holder = new List<Action<int>>();
public void Register(Action<int> func)
{
m_Holder.Add(func);
}
public List<Action<int>> ReturnWrappedList()
{
List<Action<int>> temp = new List<Action<int>>();
//for (int i = 0; i < m_Holder.Count; i++) //Works - gives 1, 2
//{
// var action = m_Holder[i];
// temp.Add(p => action(p));
//}
foreach (var action in m_Holder)
{
temp.Add(p => action(p)); //Fails - gives 2,2
//temp.Add(new Action<int>(action)); Works - gives 1,2
}
return temp;
}
}
class Program
{
static void Main(string[] args)
{
var disp = new Dispatcher();
var hold1 = new Holder(1, disp);
var hold2 = new Holder(2, disp);
disp.ReturnWrappedList().ForEach(p => p(1));
}
}
This is the infamous "closing over the loop variable" gotcha.
Closing over the loop variable considered harmful (and part two)
Have you tried:
foreach (var action in m_Holder)
{
var a = action;
temp.Add(p => a(p));
}
This is the classic issue of a captured closure with a scope that isn't what you expect. In the foreach, the action has outer scope, so the execution captures the last value of the loop. In the for case, you create the action in inner scope, so the closure is over the local value at each iteration.
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.