I apologize in advance... I'm new to C# and am trying to teach myself (badly)!
I've been set a number of tasks to decipher some code and explain what it's doing, but on these three pieces I'm really struggling - I only have the code detailed - nothing else to put it onto context... otherwise I think I'd be fine.
if (HasMark && !MarkReference.Entity.IsValidOn(DateSignedUp.Value)) {
LogError(PersonMessages.MarkNotValidOnDateSignedUp(DateSignedUp));
My thought:
If HasMark variable is true and the DateSignedUp value is false, then call the PersonMessages error and specify the DateSigned up value.
if (From.HasValue && From.Value<Session.Current.VirtualNow) logError(PersonNonMessages.PastHoliday);
My thought: If From is true and From equals (whatever) "Session.Current.VirtualNow" is, through up the PersonNonMessages.PastHoliday error.
if (pastAuditLogs != null) pastAuditLogs.ForEach(x => x.AuditLogs = auditLogs);
My thought: If pastAuditLogs isn't null, for each entry in the pastAuditLog, loop through and find the latest entry for each.
Could anyone please advise on if any of my assumptions above are correct, or if I'm even close to understanding the code?
Apologies it's so vague - if there was any other supporting code or background scenario it'd be 10x easier to understand!
Many thanks
You're using Visual Studio, correct?
You can right click on any symbol (like HasMark) and then choose Show Definition. Then, you can see a white arrow in a blue circle at the upper left of your pane, that takes you back to where you were. This is an incredibly handy feature for code archaelogy.
Also, if you hover your cursor over code you often get a bit of explanation in a tooltop.
Let's tear apart this hunk of code bit by bit...
if (HasMark && !MarkReference.Entity.IsValidOn(DateSignedUp.Value)) {
LogError(PersonMessages.MarkNotValidOnDateSignedUp(DateSignedUp));
}
It means...
If HasMark is true....
Call the boolean-valued function MarkReference.Entity.IsValidOn() ...
Passing the value DateSignedUp.Value
If that function returns false (!) ...
Call the function PersonMessages.MarkNotValidOnDateSignedUp() ...
Passing the value DateSignedUp ...
and pass the returned value to the function LogError().
The && operator won't perform step 2 above if HasMark is false.
The order I've shown here is important. In this bit of code, the second line seems to have the side effect of marking something not valid. But maybe that MarkNotValidOnDateSignedUp() method just looks up some message to toss into LogError().
To know exactly what all this stuff means isn't possible without having your code base present. That's what you use Show Definition to do.
<CTRL><SHIFT><F> activates a Find All function. That's handy too.
Can you run this stuff in the debugger? If so, step through it with Step Into and see what it does.
Pro tip: There's an addon package to Visual Studio called Resharper. It helps with this kind of code archaelogy. They have a free evaluation and sell personal copies for short money.
Related
The request:
I'd like to be able to write an analyzer that can provide a proxy value for a certain expression and trigger a re-parsing of the document.
The motivation:
Our code is littered with ABTests that can be either in a deployed or active state with a control and variant group.
Determining a test's state is done through a database lookup.
For the tests that are deployed with the control group, any statement of the following form will evaluate to false:
if(ExperimentService.IsInVariant(ABTest.Test1))
{
}
I'm trying to provide tooling to make this easier to deal with at develop time by greying it out in this scenario.
As it is, this is fairly limited and not robust because I basically have to play parser myself.
What if the actual code is
if(!ExperimentService.IsInVariant(ABTest.Test1))
or
if(ExperimentService.IsInVariant(ABTest.Test1) || true)
or
var val = ..... && (ExperimentService.IsInVariant(ABTest.Test1);
if(val){
// val is always going to be false if we deployed control.
}
A possible approach I could see provided is by allowing us to write analyzers that are fired once and rewrite the tree before the actual IDE parsing happens (or, well, just parse it a second time).
These should only fire once and allow us to replace a certain expression with another. This would allow me to swap all of these experiment calls for true and false literals.
As a result, these sections could benefit from all the other IDE features such as code greying for unreachable code but also more intricate ones like a variable that will never have a different value
Obviously this is just an example and I'm not sure how feasible it is. Any suggestions for a proper feature or something that already exists are more than welcome.
I don't think there's an approach that doesn't have a compromise.
ReSharper doesn't support rewriting the AST before analysis - that would just rewrite the text in the file.
You could write an analyser that greys out the code, by applying a "dead code" highlight to the contents of the if block, but as you say, you'd need to parse the code and analyse control flow in order to get it correct, and I think that would be very difficult (ReSharper does provide a control flow graph, so you could walk it, but it would be up to you to A. find the return value of IsInVariant and B. trace that value through whatever conditions, && or || statements until you find an appropriate if block).
Alternatively, you could mark the IsInVariant method with the ContractAnnotation attribute, something like:
[ContractAnnotation("=> false")]
public bool IsInVariant(string identifier)
{
// whatever...
}
This will tell ReSharper's analysis that this method always returns false (you can also say it will return true/false/null/not null based on specific input). Because it always returns false, ReSharper will grey out the code in the if statement, or the else branch if you do if (!IsInVariant(…)).
The downside here is that ReSharper will also add a warning to the if statement to tell you that the expression always returns false. So, it's a compromise, but you could change the severity of that warning to Hint, so it's not so intrusive.
This is not enough to really warrant the bounty, but one solution that might apply from the developer documentation is to create a custom language and extend the basic rules.
You said
I'm trying to provide tooling to make this easier to deal with at develop time by greying it out in this scenario.
Greying out the corresponding parts might just be done by altering syntax highlighting rules.
See this example for .tt files.
This is trivial question but find myself thinking it all the time - often when debugging, I want to break right after a certain line of code executes, and rather than putting the breakpoint on the next line of code (which may be a ways down due to large comment blocks, or putting it on the last line of code and then hitting F10 to go over it after it breaks, I have this urge to put a short stub line on which I will set my breakpoint.
In VBA I'd use DoEvents for this, the shortest thing in c# I've found that doesn't create an annoying compiler warning (the variable 'x' is declared but never used) is:
int x = 1; x++;
Is this about as good as you can get, or is there some other obvious approach to this I'm not aware of?
Note: I am aware of suppressing warnings via:
#pragma warning disable 0168 // get rid of 'variable is never used warning'
...but find it sporadically doesn't work.
For debugging purposes, what I always do is use System.Diagnostics.Debugger.Break(). In practice, it's just like inserting a break point on a statement but is much easier to determine its function after the fact, and is maintained through source control between users and systems. It doesn't clutter your Breakpoints window. It also, helpfully enough, will not trigger when running in Release mode, allowing you to place these in areas of critical importance, and leave them in without harming your customer releases.
As an alternate suggestion, following InBetween's comment:
If, instead, you are looking for a "harmless" statement that you can simply set a breakpoint on when you desire, Thread.Sleep(0) should be similar enough to your anecdotal VBA solution to suffice for your debugging purposes.
Thread.Sleep(0). This tells the system you want to forfeit the rest
of the thread’s timeslice and let another, waiting, thread run.
-- http://blogs.msmvps.com/peterritchie/2007/04/26/thread-sleep-is-a-sign-of-a-poorly-designed-program/
This would be a less ideal solution in my mind than my first suggestion, but it may be more what you're looking for.
So you need to
write code which does nothing, but can accept a breakpoint, and
tell other programmers that it does nothing (so they don't try and "fix" it).
Make a function which does nothing:
// Call it anywhere, so you can put a breakpoint on the code
public static void DoNothing()
{
// Any code which does nothing here
}
Then call it:
... some code ...
DoNothing();
... other code ...
while(player.CloseMenu(menuType))
{
}
player.CloseMenu(menuType) will close one menu of the chosen type, or return false if there are none left of that type.
is it ok to use an empty loop like this to close all the menus of a given type?
Be careful when coming up with clever ways of doing things in code. It may save a few keystrokes in the short run, but someday someone else may look at this code and wonder:
What is this even doing?
Ok, I see what it's doing, but why was it done this way?
Is there a compelling reason for this, and should I avoid it so as to not break something else?
Keep in mind, that someone else may very well be you in several months after you've forgotten the details of this code.
Saving a few lines of code isn't really a big deal. Anything that has to be written only once is a finite amount of work. Anything that sows confusion in support going forward produces an unknown and less finite amount of work.
I'd go with more self documentation in case other people need to read it.
The problem is that you have to infer from the fact that the invocation is inferred as a bool to understand.
Maybe if you named it player.IsMoreAfterClose().
or
while(true)
{
bool b = player.CloseMenu(menuType);
if(!b) break;
}
or
bool b = true;
while(b)
{
b = player.CloseMenu(menuType);
}
I would expand on all of these answers and create a method called CloseAllMenus(MenuType menuType). Then you can put whatever kind of ugly implementation in there, and it will be obvious what it is doing when you call it. Your current code doesn't explain what exactly is happening unless you already know that there can be multiple menus of a particular type open, and that this call will only close one of them.
It'll work, obviously, but it makes the code a little hard to read/maintain. You might be better of with the loop condition being a check for any open menus, with the body of the loop closing one.
It's ok to do that as it means do something until certain condition is met. But it's better to incorporate that in the CloseMenu function so that you don't have to repeat this instruction many times and in fact it's a variation of closing menu where you want to close all menus. You can add a boolean argument to the function to indicate if you want to close all menus.
bool CloseMenu(type, closeAll){
if(closeAll)
while(exists(type))
{ close...
else
if(exists(type)
{ close...
}
Maybe the "right" thing to do is invert from While/Close with no body to For/Open with the body doing the Close operation.
foreach(var menu in player.OpenMenus)
menu.Close();
or:
player.OpenMenus.ForEach(c => c.Close());
When I used to develop in C++, I remember that Visual Studio had an entry in its Autos window whenever returning from a function call. This entry would tell me what value was returned from that function.
One might argue that if a function returns a value, then you should set a variable to that value, i.e.
int i = GetRandomInt();
But as a contrived example, suppose I wanted to do this:
CycleTushKicker( GetRandomInt());
Instead of stepping into CycleTushKicker to figure out how many lickings my kid gets, I'd just like to know the value as soon as I exit GetRandomInt.
Is there a way to get this when using C#?
EDIT -- followed #Michael Goldshetyn's advice and filed a feature suggestion on Microsoft Connect. You can place your votes here: https://connect.microsoft.com/VisualStudio/feedback/details/636130/display-return-value-from-function-in-autos-window-for-c
There is no way to see the return value of a function in the Autos pane of VS2010 when using C#. If you want to be able to see this value, you will need to assign it to a temporary variable, and then you will see this variable's value (at least in debug builds).
Update
VS2013 now offers this functionality
It is better to just use a temporary variable.
This will allow you to see this in the debugging windows, but also allow you to set a break point, and step cleanly over or through each function individually.
By doing the following:
var randomInt = GetRandomInt();
CycleTushKicker(randomInt);
You effectively create exactly the same code, but it is much simpler to debug.
I am trying to track down a very elusive bug in an application that manipulates a FlowDocument. I have shown below three consecutive lines of debugging code, together with their output:
Debug.Assert(ReferenceEquals(document1, document2));
Debug.WriteLine(document1.Blocks.Count); // 1
Debug.WriteLine(document2.Blocks.Count); // 3
Can anyone help me to understand how two references to the same object can have different values for a given property? Or am I missing something about the way ReferenceEquals works?
Thanks,
Tim
Edit:
If I change the assertion to an if block, the debugging code never runs ...
if (ReferenceEquals(document1, document2))
{
Debug.WriteLine(document1.Blocks.Count);
Debug.WriteLine(document2.Blocks.Count);
}
... which makes me feel utterly stupid, because the ReferenceEquals test is clearly working, but I don't understand why the assertion is not working.
Two things that might be happening from the top of my mind:
Accessing Blocks or Blocks.Count might mutate state (it shouldn't, but it is possible).
The object might be changed on another thread between the two calls. Do you use multi-threading in the application ?
Also, if the references are of different types (ie. document2 is of an inherited type), the property might be overloaded to return something different. You could check to see whether document1.GetType() == document2.GetType().
Edit in response to your update
Debug.Assert will only ever run, if the assembly is compiled in Debug mode. If you are running Release, it will not be run. This is because Debug.Assert is decorated with the [Conditional("DEBUG")] attribute.
It seems that the issue is the fact that you indeed have 2 different objects.
If a property has side effects it can yield different results each time you call it. E.g. DateTime.Now does not always equal DateTime.Now.
Without knowing anything more about the code, that would be my guess.
EDIT: Using Reflector on FlowDocument shows that Blocks return a new instance each time it is called. Additionally, the Count property BlockCollection is rather elaborate, so I would take a closer look at that. Unfortunately I don't know the involved types very well, so I can't immediately tell you what is wrong.
Possibilities (some of which you have already discounted in the comments):
Some external process, say something that is loading Blocks into FlowDocument, is altering the value between writes.
Heisenberg: reading the Blocks property affects it. This happens sometimes when reading rows from a data source. I'm not familiar with FlowDocument so I'm not sure how feasible this is.
If the instances were declared as different types, their references would still be equal, but the value of Blocks (or Blocks.Count) could be overridden, resulting in different return values since different code might be called - like Object.ToString() vs Int.ToString().
You're somehow calling this debug code in the middle of a loop. This could happen if you're running it in the command window or some attached debugger instead of within the application.
You have dead pixels on your screen that make the first "3" look like a "1".
You live next to a nuclear reactor.
Some things to try:
Run your .Assert code in a loop and see if the values stabilize.
Set a read/write breakpoint on the Blocks value. (I know you can do this in C, but haven't tried it in C#)
Update
Regarding your additional question about .Assert() not working as expected:
Just looked at this note on MSDN regarding Debug.Assert().
By default, the Debug.Assert method works only in debug builds. Use the Trace.Assert method if you want to do assertions in release builds. For more information, see Assertions in Managed Code.
Are you running a debug build or a release build?
Are you certain that the Blocks object reference points to the same object? Try a
Debug.Assert(ReferenceEquals(document1.Blocks, document2.Blocks));
and see if that succeeds.