if(i<2 && i>10){
//code here will never be reached or what?
}
Just in case of an integer overflow maybe?
Edit: I wrote this not knowing c# is the language used. I've used C++ but I believe that the principle is also valid for c#.
there is no single integer that satisfies the condition
the compiler may well optimize away the body of the if condition (see here for an example on compiler explorer)
however, in the case of i being volatile it is possible that the value of i changes between the i<2 and the i>10 tests. In this case the if body can be reached.
However, though it may be theoretically possible it is highly unlikely that this was the intention.
Here's my example code
#include <iostream>
using std::cout;
void foo(int i)
{
if (i < 2 && i > 10)
{
cout << "The impossible happened in foo\n";
}
}
void bar(volatile int i)
{
if (i < 2 && i > 10)
{
cout << "The impossible happened in bar\n";
}
}
It is indeed possible for some c# (assuming c# because it's tagged... not assuming integer even if it's tagged because the right-hand comparison is still an integer, so it matches the tags! ;-) ) code to go into that if... take:
public class Foo {
public static bool operator> (Foo a, int b) {
return true;
}
public static bool operator< (Foo a, int b) {
return true;
}
}
Then:
Foo i = new Foo();
if(i<2 && i>10){
Console.WriteLine("Pass!");
}
Guess the output? Check it out here
Another way, with no extra classes or operator overloading:
private static bool odd;
public static int i { get { odd = !odd; return odd ? 1 : 11; } }
Check it out
Otherwise, it could also happen if multithreading (if the value of i changes bewtween the comparisons) unless you apply correct locking
Related
I need to exit from a method when a certain condition is reached. The other lines of code should not be executes after exit Condition is reached. what is the best way for this I have tried to use Environment.Exit(0), but it causes problem in my logic.
Exit(0) does not seem to work unless in a loop
We have two possibilities: normal (return) and abnormal (throw) termination:
public static int Factorial(int value) {
// We can't compute factorial for negative and too large values
if (value < 0 || value > 12)
throw new ArgumentOutOfRangeException(nameof(value)); // Abnormal termination
if (value == 0)
return 1; // Normal termination: special case in which we know the answer
...
}
The "return" statement exits condition-blocks aswell as loops and methods.
public void myMethod(int a){
if( 1 == a) {
return;
}
// do something with a
}
As some people have already said before me, return is the way to go.
Here is an example where an if statement compares two integers and returns if they are equal:
public void isEqual(int a, int b) {
if (a == b) {
Console.WriteLine("Integers are equal");
return; //Return to executing the rest of the program.
}
else {
Console.WriteLine("Integers are not equal");
}
}
EDIT: Originally, this post's example had dealt with hash codes, so you will see some comments using param.GetHashCode(), rather than (1+param). To get more to the point, I have changed the functions to calculate one plus the absolute value of some number.
Let's say that I want to create a function that calculates the absolute value of some integer (without using Math.Abs). I could write something similar to:
int absoluteValueOfOnePlus(int param)
{
int onePlusParam= 1 + param;
return ((onePlusParam> 0) ? (onePlusParam) : (-onePlusParam) );
}
I'm looking to limit the scope of onePlusParm to within the ternary statement--something similar to:
int absoluteValueOfOnePlus(intparam)
{
return (((int onePlusParam = 1 + param) > 0) ? (onePlusParam) : (-onePlusParam) );
}
I understand that this is not valid C#, but it proves a good example for what I'm trying to perform--create some variable which exists only in the scope of a ternary operator.
The parts of a ternary expression are expressions. If the language designers were to allow what you're asking for, they would probably do it for all expressions rather than just for ternary expressions. You would then also be able to do if ((int n = foo()) != 0) bar(n);.
In C#, declarations are statements, not expressions. So the answer is no, you can't do this. However, the for statement can take a declaration, so the closest you can get to a single statement is this:
for (int i = param.GetHashCode();;)
return (i > 0) ? i : -i;
which is technically a single statement, albeit a compound one, and on two lines. But that looks awful code and I wouldn't write it like that.
If your main concern is minimizing the scope of i, then use a small scope for it:
int positiveHash(string param)
{
// Some statements here...
// ...
// Start a small scope
{
int i = param.GetHashCode();
if (...)
return ((i > 0) ? (i) : (-i) );
}
// Some more C# statements here.
// i is out of scope here.
}
I would simply write:
int GetPositiveHash(string param)
{
return Math.Abs(param.GetHashCode());
}
or
int GetPositiveHash(string param)
{
int hashCode = param.GetHashCode();
return Math.Abs(hashCode);
}
The aids readability, maintainability and more importantly in this case avoid premature optimization which is the root of all evil.
If you are really worried about performance then profile you code and see where your biggest bottlenecks are. I'd be surprised if GetPosiitiveHash() is causing the biggest bottleneck.
You might like to have a look at the .Net Framework source code for String.GetHashCode(). You'll see that a ternary operator is going to have quite a minimal saving compared what going on inside the GetHashCode() method.
It's worth remembering:
The full version of the quote is "We should forget about small
efficiencies, say about 97% of the time: premature optimization is the
root of all evil." and I agree with this. Its usually not worth
spending a lot of time micro-optimizing code before its obvious where
the performance bottlenecks are.
from The fallacy of premature optimization
You could substitute having a data variable (i) in scope to having a function variable in scope. The advantage is a function is more likely to be written only once and not likely to be misused.
int positiveHash(string param)
{
Func<int, int> absoluteValue = i => (i > 0) ? i : -1;
return absoluteValue(param.GetHashCode());
}
And my attempt
static int positiveHash(string param)
{
return new List<string>() {param}.Select(s => s.GetHashCode()).Select(i => (i > 0) ? (i) : (-i)).Single();
}
(Of course your code (and mine) is bad,you need to split your method into 2 smaller ones)
and the updated question
static int absoluteValueOfOnePlus(int intparam)
{
return new List<int> { intparam }.Select(n => n + 1).Select(i => (i > 0) ? (i) : (-i)).Single();
}
Besides just creating a new block you could also use the built in Absolute value function Math.Abs(...) or define your own lambda/function;
...built in ...
public static int hash(string param)
{
return Math.Abs(param.GetHashCode());
}
... lambda ...
static Func<int, int> abs = i => i > 0 ? i : -i;
public static int hash(string param)
{
return abs(param.GetHashCode());
}
... static function ...
static int Abs(int i)
{
return i > 0 ? i : -i;
}
public static int hash(string param)
{
return Abs(param.GetHashCode());
}
I need to perform comparison between 2 methods in c# code,
I found the SyntaxNode.IsEquivalentTo, but in case the methods are:
public void Method1()
{
//hello
}
and
public void Method1()
{
}
the return value is : True.
is there any other way with Rslyn API to perform comparison including comments trivia??
(and in the example above to get: False??)
(The reason i'm not using regular string comparison is that i wan't that spaces and new line will not count as difference, for example:
public void Method1()
{
int i=1;
}
and
public void Method1(){
int i=1 ;
}
will be equal.
At the time of writing this, there is no built-in method to support such comparison, but it is easy to write one using syntax rewriters.
The basic idea is very simple. Write a CSharpSyntaxRewriter that will remove all the non-comment trivia from both of the compared nodes and then compare the newly created nodes by using the built in IsEquivalentTo() method.
The below code does what you are looking for. To compare two nodes (MethodDeclarationSyntax in your case) just call:
firstNode.IsEquivalentToWithCommentsPreserved(secondNode);
Here is the implementation:
public static class SyntaxNodeExtensions
{
public static bool IsEquivalentToWithCommentsPreserved(this SyntaxNode syntaxNode, SyntaxNode otherNode)
{
var triviaRemover = new NonCommentTriviaRemover();
return triviaRemover.Visit(syntaxNode)
.IsEquivalentTo(triviaRemover.Visit(otherNode));
}
private class NonCommentTriviaRemover : CSharpSyntaxRewriter
{
private static readonly SyntaxTrivia EmptyTrivia = default(SyntaxTrivia);
public override SyntaxTrivia VisitTrivia(SyntaxTrivia trivia)
{
return trivia.IsKind(SyntaxKind.SingleLineCommentTrivia) ||
trivia.IsKind(SyntaxKind.MultiLineCommentTrivia)
? trivia // Preserve comments by returning the original comment trivia.
: EmptyTrivia; // Remove all other trivias.
}
}
}
Keep in mind that this code does not ignore eventual differences in trivias in comments. That means, these two versions of the methods will be considered as not being equivalent:
void Method()
{
// Some comment.
}
void Method()
{
// Some comment.
}
Let me know if you maybe need to ignore these differences as well. I can then extend the solution to cover that case as well.
I quickly tried the solution on the following non-trivial example and it worked fine:
var firstCode =
#"
// First comment.
// Second comment.
int x(int a)
{
// This is a comment.
// And this as well.
if (a == 1) // This also
{
return 0 ;
}
/*
Multi line comment.
*/if(a == -5) return -10 ;
if (a == 2)
return 0 ;
return 5;
}
";
var secondCode =
#"
// First comment.
// Second comment.
int x(int a)
{
// This is a comment.
// And this as well.
if (a
== 1) // This also
{
return 0 ;
}
/*
Multi line comment.
*/
if(a == -5) return -10 ;
if (a == 2) return 0 ;
return 5;
}
";
var firstMethod = CSharpSyntaxTree.ParseText(firstCode).GetRoot().DescendantNodes().OfType<MethodDeclarationSyntax>().First();
var secondMethod = CSharpSyntaxTree.ParseText(secondCode).GetRoot().DescendantNodes().OfType<MethodDeclarationSyntax>().First();
Console.WriteLine($"{firstMethod.IsEquivalentTo(secondMethod)}"); // Prints false.
Console.WriteLine($"{firstMethod.IsEquivalentToWithCommentsPreserved(secondMethod)}"); // Prints true.
Still, before using the code in the production it would be good to write proper unit test for it, null-checks etc. ;-)
If they need to be exactly the same, you could simply call node.ToString() on the nodes and compare the strings.
I call c++/cli method from c# in this method:
bool SetProperty(Element element, Node referencePoint, List<Materializer> materializers, List<ulong> properties)
{
// Loop over STLs
for (int i = 0; i < materializers.Count; i++)
{
Materializer materializer = materializers[i];
PentalTreeNode pentalTreeRoot = pentalTreeDatasets[i].top;
if (materializer.IsPointInside(referencePoint.X, referencePoint.Y, referencePoint.Z, pentalTreeRoot))
{
element.PropertyId = properties[i];
return true;
};
}
return false;
}
C++/cli method is this:
bool IsPointInside(double x, double y, double z, PentalTreeNode ^root)
{
int intersectionCount = 0;
Math3d::M3d rayPoints[2], intersectionPoint;
rayPoints[0].set(x,y,z);
rayPoints[1].set(x,y,1.0e6);
if(_box->IsContainingPoint(x,y,z))
{
intersectionCount=CountIntersects(x,y,z,root);
return (intersectionCount%2!=0);
}
}
What is wrong, because c++/cli method doesn't return always the same result?
How to pin or marshal?
Method in c++/cli(Maybe this not ok?):
int CountIntersects(double x, double y, double z, PentalTreeNode ^root)
{
Math3d::M3d rayPoints[2], intersectionPoint;
rayPoints[0].set(x,y,z);
rayPoints[1].set(x,y,1.0e6);
if(!root)
return 0;
else
{
int special = CountIntersects(x,y,z,root->special);
if (x <= root->xMax && x >= root->xMin && y <= root->yMax && y >= root->yMin)
{
if( _stlMesh->IsRayIntersectsPoly(root->index, rayPoints, intersectionPoint))
{
return (1 + special);
}
else
return special;
}
else
{
if (y>root->yMax)
{
return (CountIntersects(x,y,z,root->top)+special);
}
else if(y<root->yMin)
{
return (CountIntersects(x,y,z,root->bottom)+special);
}
else if(x<root->xMin)
{
return (CountIntersects(x,y,z,root->left)+special);
}
else if(x>root->xMax)
{
return (CountIntersects(x,y,z,root->right)+special);
}
else
return special;
}
}
}
if( _stlMesh->IsRayIntersectsPoly(root->index, rayPoints, intersectionPoint))
There's one possible flaw in this particular statement, you've never initialized intersectionPoint. C++ lets you get away with this, it doesn't have anything similar to C#'s definite assignment rules. It isn't 100% clear whether that's the real problem, the variable might be passed by reference.
In the Debug build, such an uninitialized variable will have a predictable value. Something you can easily see in the debugger when you switch it to hexadecimal display mode. Fields in this struct or class will contain the value 0xcccccccc, a value that's apt to generate nonsensical results or crash your code with an access violation. In the Release build, the /RTC option isn't turned on and you'll get entirely random values in the variable.
Which corresponds very well with the description of your problem, so high odds that this is indeed the problem. Be sure to use the debugger to find problems like this, you can easily see the value of local variables with the Autos debugger window as you single-step through the code.
You are not calling a C++ method! You are calling a C++/CLI method. And therefore it is normal .NET code and it is always passed correctly. There is no need to pin or marshal anything in C# im this case!
If it returns not the expected values, you should try to find the problem in you C++/CLI project.
Take the following:
var x = new Action(() => { Console.Write("") ; });
var y = new Action(() => { });
var a = x.GetHashCode();
var b = y.GetHashCode();
Console.WriteLine(a == b);
Console.WriteLine(x == y);
This will print:
True
False
Why is the hashcode the same?
It is kinda surprising, and will make using delegates in a Dictionary as slow as a List (aka O(n) for lookups).
Update:
The question is why. IOW who made such a (silly) decision?
A better hashcode implementation would have been:
return Method ^ Target == null ? 0 : Target.GetHashcode();
// where Method is IntPtr
Easy! Since here is the implementation of the GetHashCode (sitting on the base class Delegate):
public override int GetHashCode()
{
return base.GetType().GetHashCode();
}
(sitting on the base class MulticastDelegate which will call above):
public sealed override int GetHashCode()
{
if (this.IsUnmanagedFunctionPtr())
{
return ValueType.GetHashCodeOfPtr(base._methodPtr);
}
object[] objArray = this._invocationList as object[];
if (objArray == null)
{
return base.GetHashCode();
}
int num = 0;
for (int i = 0; i < ((int) this._invocationCount); i++)
{
num = (num * 0x21) + objArray[i].GetHashCode();
}
return num;
}
Using tools such as Reflector, we can see the code and it seems like the default implementation is as strange as we see above.
The type value here will be Action. Hence the result above is correct.
UPDATE
My first attempt of a better implementation:
public class DelegateEqualityComparer:IEqualityComparer<Delegate>
{
public bool Equals(Delegate del1,Delegate del2)
{
return (del1 != null) && del1.Equals(del2);
}
public int GetHashCode(Delegate obj)
{
if(obj==null)
return 0;
int result = obj.Method.GetHashCode() ^ obj.GetType().GetHashCode();
if(obj.Target != null)
result ^= RuntimeHelpers.GetHashCode(obj);
return result;
}
}
The quality of this should be good for single cast delegates, but not so much for multicast delegates (If I recall correctly Target/Method return the values of the last element delegate).
But I'm not really sure if it fulfills the contract in all corner cases.
Hmm it looks like quality requires referential equality of the targets.
This smells like some of the cases mentioned in this thread, maybe it will give you some pointers on this behaviour. else, you could log it there :-)
What's the strangest corner case you've seen in C# or .NET?
Rgds GJ
From MSDN :
The default implementation of
GetHashCode does not guarantee
uniqueness or consistency; therefore,
it must not be used as a unique object
identifier for hashing purposes.
Derived classes must override
GetHashCode with an implementation
that returns a unique hash code. For
best results, the hash code must be
based on the value of an instance
field or property, instead of a static
field or property.
So if you have not overwritten the GetHashCode method, it may return the same. I suspect this is because it generates it from the definition, not the instance.