Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 18 hours ago.
Improve this question
TL;DR
If a C# Action referencing a class method still has a reference to the original Target, then why is this being changed when I invoke the Action and set breakpoints in that method?
More Context
I have the following setup in a .NET project:
// MyClass.cs
public class MyClass
{
private float _someValue = -1f;
private int _instanceId = 12345;
public void Method()
{
Updater.Instance.RegisterUpdate(_instanceId, doStuff);
}
private void doStuff(float deltaTime)
{
// Do stuff with _someValue
}
}
// Updater.cs
public class Updater
{
public static Updater Instance = new();
private readonly List<Action<float>> _updateActions = new();
public void RegisterUpdate(int instanceId, Action<float> updateAction)
{
// Validation...
_updateActions.Add(updateAction);
}
public void Update()
{
foreach (Action<float> action in _updateActions)
action.Invoke(Time.deltaTime);
}
}
Essentially, Updater wraps a list of registered Actions, and invokes them all when Update is called.
In Visual Studio, I can set breakpoints in MyClass.doStuff(), and they are getting hit when Updater.Update() is called. Unfortunately, while paused on a breakpoint, I get no value when I hover over the value of _someValue, nor is the field even mentioned in the Locals Window, and when I enter _someValue in the Immediate Window, I get "The identifier _someValue is not in the scope". In addition, the this value in the Locals Window is of type Updater, not MyClass.
And yet, everything is working fine. The conditional logic inside doStuff that works with _someValue is still working as expected when I step through, I just can't inspect the values as I step, which makes things difficult to debug. Also, when I go up the call stack to Updater.Update and inspect the current element of _updateActions, I can see that its Target property is correctly set to the instance of MyClass. So what is happening here? Trying to figure out what this is feels like JavaScript crap lol, not C#.
Turns out the issue was something in my actual code that was not captured in the minimum working example in my question. That is, in my real code, doStuff was a local function inside of Method. If doStuff is a separate method, as in my question, then this is of the correct MyClass type. Strangely, I can only repro the this-changing behavior of local functions in Unity components, not in vanilla C# classes, so this may be a result of the Mono compiler that Unity uses on the backend.
Anyway, thank you to the commenters for helping me get here. Hopefully this helps someone in the future.
Related
So in JavaScript, you can call toString() on a function to return it's source code. However, no such construct exists for C# delegates.
Let's say I have this code sample here:
void DoThing()
{
Console.WriteLine("I did a thing");
}
void Execute(Action act)
{
act();
}
public static int Main(string[] args)
{
Execute(DoThing);
Execute(() => Console.WriteLine("llama lambda"));
}
If I debug this code in Visual Studio 2019, and put a breakpoint on Execute, I can look at the properties of act.
For the first call with DoThing, Visual Studio can at least give me the name of the method and it's return type (Void DoThing()), but not the source code. If I have multiple DoThings in my source code, this will not be very helpful at all.
But for the lambda, I get no useful info in the debugger ({Method = {Void <Process>b__11_0()}}).
Now, of course in this small example code, it is pretty easy to find the functions by just retracing the call stack, but in some cases, this is a very long and arduous endeavour, especially when it needs to be done multiple times.
I searched around on google and I couldn't find a simple answer to this question, or even find anywhere where this question was asked:
Is there any way to find the source code of a delegate in C# when using the Visual Studio debugger (without just retracing the call stack)?
If yes, how?
And if no, why?
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 1 year ago.
Improve this question
I have simple scenario where I started to repeat same code multiple times, so I decided to move it in a private method, depending on a if/else it's being edited and my variables that are listed below might overwrite it's value which is perfectly fine:
ProductResponse identificationResults = new ProductResponse(); // I understand this assignment gets overridden in private method below but that is goal
long? productIdentificationRecordId = null; // I understand this assignment gets overridden in private method below but that is goal
I'm invoking my method on a few places in a code that's reason why I created private method to avoid code repetition in same file:
await SetProductStatusAndPerformDbActions(productCompany, userId );
private async Task SetProductStatusAndPerformDbActions(Company productCompany, long userId, ProductType productType, ProductStatus status, long? productIdentificationRecordId, ProductResponse identificationResults, CancellationToken cancellationToken)
{
status = GetCompanyProductStatus(productCompany.Id, identificationResults);
productIdentificationRecordId = await PerformDbAction(status, productType, userId, cancellationToken); // underlined this code
identificationResults = await IdentifyCompanyProduct(productCompany, cancellationToken); // underlined this code
}
Visual Studio says 'Remove this useless assignment to a local variable
productIdentificationRecordId'
Visual Studio says 'Remove this useless assignment to a local variable
identificationResults'
I understand this assignments gets overridden in private method below but that is point of private method because I want to use for example productIdentificationRecordId and its new value right after I call this private method because goal of private method is to modify it and that is it..
I'm not using vars which might cause this warning so I don't know what to do here.
How this could be written to avoid this scenarios ?
Edit:
Added screenshot from the private method, variables are grayed as they are not used:
Because these parameters are not being passed by reference, setting them to any value will only change the value of the parameter variables local to your helper method: it will not impact the values that were passed in to those parameters.
Since you don't use the new values you're assigning to those parameters inside the method, Visual Studio is smart enough to recognize that setting values to them has no effect. It's warning you about that, which is good because in this case you might think your code is doing something that it's not really doing.
I've just spent the best part of an hour trying to work out why some code appered to not be working. I was getting no compilation errors of any sort, and have tracked the bug down to calling a function and doing nothing with the return value. The code was a little more involved than the sample below as Class1 is immutable, but it still demonstrates the issue:
public class Class1
{
private int MyVal = 0;
public int GetMyVal()
{
return MyVal;
}
}
public void Tester(){
Class1 Instance = new Class1();
Instance.GetMyVal();
}
The function call to GetMyVal() is as technically useless as it is technically correct. As I say the code was more involved, but this is the core issue.
I'm slightly surprised that VS 2013 (For Web) fails to highlight the issue as clearly nothing is gained from calling GetMyVal. Is there some switches I'm missing to detect this sort of thing or is this beyond the scope of what Visual Studio can accomplish?
I doubt there is/are (m)any editors out there can can give you what you want.
VS will tell you if you have a variable you're not referencing (at least for Pro and Ultimate. Haven't used Web for 2012/2013). However within the scope of Class1, private int MyVal is being referenced within your GetMyVal function so it will not be marked as an unreferenced property.
It can often catch useless pieces of code but I don't see how you expect it to say that your previously initialized and referenced variable is not meaningful. It has no way of knowing that the property in Class1 isn't something you want to use/modify later.
Do correct me if I am misunderstanding your question
Side note: If you can figure out a way to make it do what you're after,might I suggest writing a plugin? Bear in mind that existing plugins like Resharper and FXCop add a world of functionality
Hello I was wondering how I can setup several things in a constructor, but have it wait until right after the object is created. I am thinking along the lines of my C++ and QT days when I would create a singleshot timer for 0 seconds that would fire my setup method as soon as the object was constructed. Can I do that in C#?
I don't mind doing all the work I do in the constructor just simply seeing if there is a better way.
In C# whole object is created before executing constructor - all fields are initialized with their default or initial values (if any). If you want to delay something, consider using lazy initialization.
I'm not sure what the problem is with just putting your stuff in the constructor is - there is nothing you cant do. Maybe an example of why you would like to do this / what problem you are having, would allow us to give you a more suited answer.
Although if you really need to delay code,
public constructor()
{
Task.Factory.StartNew(()=>
{
Thread.Sleep(...delay...);
//delayed code
});
}
One way to do what you are asking is to have a static method that constructs the desired object:
class MyObject {
private MyObject() {
}
private void Setup() {
// do some configuration here
}
public static MyObject CreateObject() {
MyObject obj = new MyObject();
obj.Setup();
return obj;
}
}
Thus, you never use the class' actual constructor but instead invoke the static method that creates the object and sets it up at the same time. I am not sure why you would want to do this though, since the effect from the point of view of the caller is the same -- you wait until the object is created and its setup is complete to be able to use it.
I have a strange problem where MonoTouch seems to be either not compiling methods or not able to find a compiled method it is instructed to call, and only on the device in the Release configuration - Debug builds are fine. I've tried reproducing it with a simpler code sample with no luck, so I doubt you will be able to see the behavior with the code below. But this is essentially what I'm doing:
using System;
using MonoTouch.UIKit;
public class MyClass
{
private UINavigationController _navController;
private UIViewControler _viewController;
public UINavigationController NavController
{
get
{
if (_navController == null)
{
if (_viewController == null)
{
_viewController = new UIViewController();
}
_navController = new UINavigationController(_viewController);
}
return _navController;
}
}
}
Then, in some other method...
public void SomeMethod()
{
MyClass myClass = new MyClass();
var navController = myClass.NavController; // <-- This is where it throws
}
The exception I get is the standard JIT compile message, saying that it attempted to JIT get_NavController(). I find this very strange, because there's no virtual generics, no LINQ, the linker is off, and nothing else that normally causes JITs seems to be involved. I've also verified that it will throw for other methods and properties defined on MyClass, but not the constructor or System.Object inherited methods. Reflection reveals that myClass.GetType().GetMembers() has a MemberInfo for everything I would expect. Yet, only for Release|iPhone, I can't access these methods or properties. The only logical conclusion I can come to is that the aot compilation step is missing them, and I don't know why that would happen at all, let alone only in the Release configuration.
My question is, what could be causing such a situation, and what is the next step to fixing it? I'm not even sure where to go from here on debugging this, or what to file a bug about, because I can't reproduce it out of the context of our (much) larger project.
Update: The exact exception text was requested.
System.ExecutionException: Attempting to JIT compile method
'MyNamespace.MyClass.get_NavController ()' while running with --aot-only
This doesn't look like something that can be solved here.
I suggest filing a bug, and attach the entire project if you're unable to make a smaller test case. You can file private bugs only Xamarin employees have access to if you don't want your project to be publicly visible.
Could you try to explicitly declare the variable
UINavigationController navController = myClass.NavController;
Alternatively, I wonder if this is at all associated with needing to wait for the UIViewController.ViewDidLoad method to be called as the internals of the class may not yet have been initialized?
Just shots in the dark here, I can't think of a reason why your code wouldn't work.