Guid.Parse() or new Guid() - What's the difference? - c#

What is the difference between these two ways of converting a string to System.Guid? Is there a reason to choose one over the other?
var myguid = Guid.Parse("9546482E-887A-4CAB-A403-AD9C326FFDA5");
or
var myguid = new Guid("9546482E-887A-4CAB-A403-AD9C326FFDA5");

A quick look in the Reflector reveals that both are pretty much equivalent.
public Guid(string g)
{
if (g == null)
{
throw new ArgumentNullException("g");
}
this = Empty;
GuidResult result = new GuidResult();
result.Init(GuidParseThrowStyle.All);
if (!TryParseGuid(g, GuidStyles.Any, ref result))
{
throw result.GetGuidParseException();
}
this = result.parsedGuid;
}
public static Guid Parse(string input)
{
if (input == null)
{
throw new ArgumentNullException("input");
}
GuidResult result = new GuidResult();
result.Init(GuidParseThrowStyle.AllButOverflow);
if (!TryParseGuid(input, GuidStyles.Any, ref result))
{
throw result.GetGuidParseException();
}
return result.parsedGuid;
}

Use the version that is the most readable to you. The two are implemented almost exactly the same way.
The only real difference is that the constructor initializes itself to Guid.Empty before attempting the parse. However, the effective code is identical.
That being said, if the Guid is coming from user input, then Guid.TryParse would be better than either option. If this Guid is hard coded, and always valid, either of the above are perfectly reasonable options.

I tried performance on one milion guids and Guid.Parse seems to be a insignificantly faster. It made 10-20 milisecods difference of 800 miliseconds of total creation on my PC.
public class Program
{
public static void Main()
{
const int iterations = 1000 * 1000;
const string input = "63559BC0-1FEF-4158-968E-AE4B94974F8E";
var sw = Stopwatch.StartNew();
for (var i = 0; i < iterations; i++)
{
new Guid(input);
}
sw.Stop();
Console.WriteLine("new Guid(): {0} ms", sw.ElapsedMilliseconds);
sw = Stopwatch.StartNew();
for (var i = 0; i < iterations; i++)
{
Guid.Parse(input);
}
sw.Stop();
Console.WriteLine("Guid.Parse(): {0} ms", sw.ElapsedMilliseconds);
}
}
And output:
new Guid(): 804 ms
Guid.Parse(): 791 ms

In .Net framework v1.1 exists only 1 way -> var myguid = new Guid("9546482E-887A-4CAB-A403-AD9C326FFDA5");
Guid.Parse became available later.

Related

Is there a more efficient way to generate 40 million alphanumeric unique random strings in C# [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed 2 years ago.
Improve this question
I've created a windows-forms-based small application to generate random unique alphanumeric strings with length=8. Application is working fine with small count but it got stuck for like forever when I try to generate 40 million (as per my requirement) strings. Please help me to make it efficient so that the strings could be generated quickly.
following is the complete code I've used for it.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading.Tasks;
namespace RandomeString
{
public partial class Form1 : Form
{
private const string Letters = "abcdefghijklmnpqrstuvwxyz";
private readonly char[] alphanumeric = (Letters + Letters.ToLower() + "abcdefghijklmnpqrstuvwxyz0123456789").ToCharArray();
private static Random random = new Random();
private int _ticks;
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
if (string.IsNullOrEmpty(textBox1.Text) || string.IsNullOrWhiteSpace(textBox2.Text))
{
string message = "Please provide required length and numbers of strings count.";
string title = "Input Missing";
MessageBoxButtons buttons = MessageBoxButtons.OK;
DialogResult result = MessageBox.Show(message, title, buttons, MessageBoxIcon.Warning);
}
else
{
int ValuesCount;
ValuesCount = Convert.ToInt32(textBox2.Text);
for (int i = 1; i <= ValuesCount; i++)
{
listBox1.Items.Add(RandomString(Convert.ToInt32(textBox1.Text)));
}
}
}
public static string RandomString(int length)
{
const string chars = "abcdefghijklmnpqrstuvwxyz0123456789";
return new string(Enumerable.Repeat(chars, length)
.Select(s => s[random.Next(s.Length)]).ToArray());
}
private void button2_Click(object sender, EventArgs e)
{
try
{
StringBuilder sb = new StringBuilder();
foreach (object row in listBox1.Items)
{
sb.Append(row.ToString());
sb.AppendLine();
}
sb.Remove(sb.Length - 1, 1); // Just to avoid copying last empty row
Clipboard.SetData(System.Windows.Forms.DataFormats.Text, sb.ToString());
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
private void timer1_Tick(object sender, EventArgs e)
{
_ticks++;
this.Text = _ticks.ToString();
}
}
}
One way to speed things up is to avoid LINQ. For example, take a look at these two implementations:
public static string LinqStuff(int length)
{
const string chars = "abcdefghijklmnpqrstuvwxyz0123456789";
return new string(Enumerable.Repeat(chars, length)
.Select(s => s[random.Next(s.Length)]).ToArray());
}
public static string ManualStuff(int length)
{
const string chars = "abcdefghijklmnpqrstuvwxyz0123456789";
const int clength = 35;
var buffer = new char[length];
for(var i = 0; i < length; ++i)
{
buffer[i] = chars[random.Next(clength)];
}
return new string(buffer);
}
Running it through this:
private void TestThis(long iterations)
{
Console.WriteLine($"Running {iterations} iterations...");
var sw = new Stopwatch();
sw.Start();
for (long i = 0; i < iterations; ++i)
{
LinqStuff(20);
}
sw.Stop();
Console.WriteLine($"LINQ took {sw.ElapsedMilliseconds} ms.");
sw.Reset();
sw.Start();
for (long i = 0; i < iterations; ++i)
{
ManualStuff(20);
}
sw.Stop();
Console.WriteLine($"Manual took {sw.ElapsedMilliseconds} ms.");
}
With this:
TestThis(50_000_000);
Yielded these results:
LINQ took 28272 ms.
Manual took 9449 ms.
So by using LINQ, you increase the time it takes to generate strings by 3 times.
You could tweak this more and squeeze out a few more seconds, probably (for example, send in the same char[] buffer to each call)
Don't use linq
pre-allocate the memory
don't put it in to a UI control
use as many cores and threads as you can.
use direct memory.
Write the results to a file, instead of using the clipboard
This could likely be done quicker and even more efficiently, see notes. However, I can generate the chars in under 200ms
Note : Span<T> would give better results, however due to the lamdas it's just easier to take the small hit from fixed and use pointers
private const string Chars = "abcdefghijklmnpqrstuvwxyz0123456789";
private static readonly ThreadLocal<Random> _random =
new ThreadLocal<Random>(() => new Random());
public static unsafe void Do(byte[] array, int index)
{
var r = _random.Value;
fixed (byte* pArray = array)
{
var pLen = pArray + ((index + 1) * 1000000);
int i = 1;
for (var p = pArray + (index * 1000000); p < pLen; p++ ,i++)
if ((i % 9) == 0) *p = (byte)'\r';
else if ((i % 10) == 0) *p = (byte)'\n';
else *p = (byte)Chars[r.Next(35)];
}
}
public static async Task Main(string[] args)
{
var array = new byte[40000000 * ( 8 + 2)];
var sw = Stopwatch.StartNew();
Parallel.For(0, 39, (index) => Do(array, index));
Console.WriteLine(sw.Elapsed);
sw = Stopwatch.StartNew();
await using (var fs = new FileStream(#"D:\asdasd.txt", FileMode.Create,FileAccess.Write,FileShare.None, 1024*1024,FileOptions.Asynchronous|FileOptions.SequentialScan))
await fs.WriteAsync(array,0, array.Length);
Console.WriteLine(sw.Elapsed);
}
Output
00:00:00.1768141
00:00:00.4369418
Note 1 : I haven't really put much thought into this apart from the raw generation, obviously there are other considerations.
Note 2 : Also this will end up on the large object heap, so buyer beware. You would need to generate them straight to file so save this from ending up on the LOB
Note 3 : I give no guarantees about the random distribution, likely a different random number generator would be better overall
Note 4 : I used 40 index's because the math was easy, you would get slightly better results if you could match your threads to cores

Chain linked classes

I have created long chains of classes, with each link(class) knowing only the next and previous link.
I see great advantage over Arrays when the index is not important.
public class ChainLink
{
public ChainLink previousLink, nextLink;
// Accessors here
}
Questions :
What is this technique actually called? (I don't know what to search)
Is there a .Net class that does the same thing?
Is there a noticeable performance impact vs. Array or List?
Example of the Accessors I use
Assign to the chain :
public ChainLink NextLink {
get{ return _nextLink;}
set {
_nextLink = value;
if (value != null)
value._previousLink = this;
}
}
public void InsertNext (ChainLink link)
{
link.NextLink = _nextLink;
link.PreviousLink = this;
}
Shortening the chain :
If I un-assign the next link of a chain, leaving the remaining links un-referenced by the main program, the garbage collector will dispose of the data for me.
Testing circular referencing :
public bool IsCircular ()
{
ChainLink link = this;
while (link != null) {
link = link._nextLink;
if (link == this)
return true;
}
return false;
}
Offset index :
public ChainLink this [int offset] {
get {
if (offset > 0 && _nextLink != null)
return _nextLink [offset - 1];
if (offset < 0 && _previousLink != null)
return _previousLink [offset + 1];
return this;
}
}
1) This structure is called a double linked list
2) This implementation exists in C# through LinkedList
3) There is a lot of articles on this topic :
here or
this SO post
Others have answered the question about what this is called and the equivalent .Net class (a LinkedList), but I thought I'd quickly look at the speed of your ChainLink vs an array and a List.
I added a method Foo() to your ChainLink class so that there was something to access for each object instance:
public class ChainLink
{
public ChainLink previousLink, nextLink;
// Accessors here
public void Foo()
{ }
}
The first method creates an array and then times how long it takes to access each item in the array:
private void TestArray()
{
// Setup the Array
ChainLink[] Test = new ChainLink[1000000];
for (int i = 0; i < 1000000; i++)
Test[i] = new ChainLink();
// Use a Stopwatch to measure time
Stopwatch SW;
SW = new Stopwatch();
SW.Start();
// Go through items in the array
for (int i = 0; i < Test.Length; i++)
Test[i].Foo();
// Stop timer and report results
SW.Stop();
Console.WriteLine(SW.Elapsed);
}
Next, I created a method to use a List<T> and time how long it takes to access each item in it:
private void TestList()
{
// Setup the list
List<ChainLink> Test = new List<ChainLink>();
for (int i = 0; i < 1000000; i++)
Test.Add(new ChainLink());
// Use a Stopwatch to measure time
Stopwatch SW;
SW = new Stopwatch();
SW.Start();
// Go through items in the list
for (int i = 0; i < Test.Count; i++)
Test[i].Foo();
// Stop timer and report results
SW.Stop();
Console.WriteLine(SW.Elapsed);
}
Finally, I created a method to use your ChainLink and move through the next item until there are no more:
private void TestChainLink()
{
// Setup the linked list
ChainLink Test = new ChainLink();
for (int i = 0; i < 1000000; i++)
{
Test.nextLink = new ChainLink();
Test = Test.nextLink;
}
// Use a Stopwatch to measure time
Stopwatch SW;
SW = new Stopwatch();
SW.Start();
// Go through items in the linked list
while (Test != null)
{
Test.Foo();
Test = Test.nextLink;
}
// Stop timer and report results
SW.Stop();
Console.WriteLine(SW.Elapsed);
}
Running each of these yields some revealing results:
TestArray(): 00:00:00.0058576
TestList(): 00:00:00.0103650
TestChainLink(): 00:00:00.0000014
Multiple iterations reveal similar figures.
In conclusion, your ChainLink is about 4,100 times faster than an array, and about 7,400 times faster than a List.

Why is the regular multiplication operator is much more efficient than the BigMul method?

I've searched for the differences between the * operator and the Math.BigMul method, and found nothing. So I've decided I would try and test their efficiency against each other. Consider the following code :
public class Program
{
static void Main()
{
Stopwatch MulOperatorWatch = new Stopwatch();
Stopwatch MulMethodWatch = new Stopwatch();
MulOperatorWatch.Start();
// Creates a new MulOperatorClass to perform the start method 100 times.
for (int i = 0; i < 100; i++)
{
MulOperatorClass mOperator = new MulOperatorClass();
mOperator.start();
}
MulOperatorWatch.Stop();
MulMethodWatch.Start();
for (int i = 0; i < 100; i++)
{
MulMethodClass mMethod = new MulMethodClass();
mMethod.start();
}
MulMethodWatch.Stop();
Console.WriteLine("Operator = " + MulOperatorWatch.ElapsedMilliseconds.ToString());
Console.WriteLine("Method = " + MulMethodWatch.ElapsedMilliseconds.ToString());
Console.ReadLine();
}
public class MulOperatorClass
{
public void start()
{
List<long> MulOperatorList = new List<long>();
for (int i = 0; i < 15000000; i++)
{
MulOperatorList.Add(i * i);
}
}
}
public class MulMethodClass
{
public void start()
{
List<long> MulMethodList = new List<long>();
for (int i = 0; i < 15000000; i++)
{
MulMethodList.Add(Math.BigMul(i,i));
}
}
}
}
To sum it up : I've created two classes - MulMethodClass and MulOperatorClass that performs both the start method, which fills a varible of type List<long with the values of i multiply by i many times. The only difference between these methods are the use of the * operator in the operator class, and the use of the Math.BigMul in the method class.
I'm creating 100 instances of each of these classes, just to prevent and overflow of the lists (I can't create a 1000000000 items list).
I then measure the time it takes for each of the 100 classes to execute. The results are pretty peculiar : I've did this process about 15 times and the average results were (in milliseconds) :
Operator = 20357
Method = 24579
That about 4.5 seconds difference, which I think is a lot. I've looked at the source code of the BigMul method - it uses the * operator, and practically does the same exact thing.
So, for my quesitons :
Why such method even exist? It does exactly the same thing.
If it does exactly the same thing, why there is a huge efficiency difference between these two?
I'm just curious :)
Microbenchmarking is art. You are right the method is around 10% slower on x86. Same speed on x64. Note that you have to multiply two longs, so ((long)i) * ((long)i), because it is BigMul!
Now, some easy rules if you want to microbenchmark:
A) Don't allocate memory in the benchmarked code... You don't want the GC to run (you are enlarging the List<>)
B) Preallocate the memory outside the timed zone (create the List<> with the right capacity before running the code)
C) Run at least once or twice the methods before benchmarking it.
D) Try to not do anything but what you are benchmarking, but to force the compiler to run your code. For example checking for an always true condition based on the result of the operation, and throwing an exception if it is false is normally good enough to fool the compiler.
static void Main()
{
// Check x86 or x64
Console.WriteLine(IntPtr.Size == 4 ? "x86" : "x64");
// Check Debug/Release
Console.WriteLine(IsDebug() ? "Debug, USELESS BENCHMARK" : "Release");
// Check if debugger is attached
Console.WriteLine(System.Diagnostics.Debugger.IsAttached ? "Debugger attached, USELESS BENCHMARK!" : "Debugger not attached");
// High priority
Process.GetCurrentProcess().PriorityClass = ProcessPriorityClass.High;
Stopwatch MulOperatorWatch = new Stopwatch();
Stopwatch MulMethodWatch = new Stopwatch();
// Prerunning of the benchmarked methods
MulMethodClass.start();
MulOperatorClass.start();
{
// No useless method allocation here
MulMethodWatch.Start();
for (int i = 0; i < 100; i++)
{
MulMethodClass.start();
}
MulMethodWatch.Stop();
}
{
// No useless method allocation here
MulOperatorWatch.Start();
for (int i = 0; i < 100; i++)
{
MulOperatorClass.start();
}
MulOperatorWatch.Stop();
}
Console.WriteLine("Operator = " + MulOperatorWatch.ElapsedMilliseconds.ToString());
Console.WriteLine("Method = " + MulMethodWatch.ElapsedMilliseconds.ToString());
Console.ReadLine();
}
public class MulOperatorClass
{
// The method is static. No useless memory allocation
public static void start()
{
for (int i = 2; i < 15000000; i++)
{
// This condition will always be false, but the compiler
// won't be able to remove the code
if (((long)i) * ((long)i) == ((long)i))
{
throw new Exception();
}
}
}
}
public class MulMethodClass
{
public static void start()
{
// The method is static. No useless memory allocation
for (int i = 2; i < 15000000; i++)
{
// This condition will always be false, but the compiler
// won't be able to remove the code
if (Math.BigMul(i, i) == i)
{
throw new Exception();
}
}
}
}
private static bool IsDebug()
{
// Taken from http://stackoverflow.com/questions/2104099/c-sharp-if-then-directives-for-debug-vs-release
object[] customAttributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(DebuggableAttribute), false);
if ((customAttributes != null) && (customAttributes.Length == 1))
{
DebuggableAttribute attribute = customAttributes[0] as DebuggableAttribute;
return (attribute.IsJITOptimizerDisabled && attribute.IsJITTrackingEnabled);
}
return false;
}
E) If you are really sure your code is ok, try changing the order of the tests
F) Put your program in higher priority
but be happy :-)
at least another persons had the same question, and wrote a blog article: http://reflectivecode.com/2008/10/mathbigmul-exposed/
He did the same errors you did.

Using properties and performance

I was optimizing my code, and I noticed that using properties (even auto properties) has a profound impact on the execution time. See the example below:
[Test]
public void GetterVsField()
{
PropertyTest propertyTest = new PropertyTest();
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
propertyTest.LoopUsingCopy();
Console.WriteLine("Using copy: " + stopwatch.ElapsedMilliseconds / 1000.0);
stopwatch.Restart();
propertyTest.LoopUsingGetter();
Console.WriteLine("Using getter: " + stopwatch.ElapsedMilliseconds / 1000.0);
stopwatch.Restart();
propertyTest.LoopUsingField();
Console.WriteLine("Using field: " + stopwatch.ElapsedMilliseconds / 1000.0);
}
public class PropertyTest
{
public PropertyTest()
{
NumRepet = 100000000;
_numRepet = NumRepet;
}
int NumRepet { get; set; }
private int _numRepet;
public int LoopUsingGetter()
{
int dummy = 314;
for (int i = 0; i < NumRepet; i++)
{
dummy++;
}
return dummy;
}
public int LoopUsingCopy()
{
int numRepetCopy = NumRepet;
int dummy = 314;
for (int i = 0; i < numRepetCopy; i++)
{
dummy++;
}
return dummy;
}
public int LoopUsingField()
{
int dummy = 314;
for (int i = 0; i < _numRepet; i++)
{
dummy++;
}
return dummy;
}
}
In Release mode on my machine I get:
Using copy: 0.029
Using getter: 0.054
Using field: 0.026
which in my case is a disaster - the most critical loop just can't use any properties if I want to get maximum performance.
What am I doing wrong here? I was thinking that these would be inlined by the JIT optimizer.
Getters/Setters are syntactic sugar for methods with a few special conventions ("value" variable in a setter", and no visible parameter list).
According to this article, "If any of the method's formal arguments are structs, the method will not be inlined." -- ints are structs. Therefore, I think this limitation applies.
I haven't looked at the IL produced by the following code, but I did get some interesting results that I think shows this working this way...
using System;
using System.Diagnostics;
public static class Program{
public static void Main()
{
PropertyTest propertyTest = new PropertyTest();
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
propertyTest.LoopUsingField();
Console.WriteLine("Using field: " + stopwatch.ElapsedMilliseconds / 1000.0);
stopwatch.Restart();
propertyTest.LoopUsingBoxedGetter();
Console.WriteLine("Using boxed getter: " + stopwatch.ElapsedMilliseconds / 1000.0);
stopwatch.Restart();
propertyTest.LoopUsingUnboxedGetter();
Console.WriteLine("Using unboxed getter: " + stopwatch.ElapsedMilliseconds / 1000.0);
}
}
public class PropertyTest
{
public PropertyTest()
{
_numRepeat = 1000000000L;
_field = 1;
Property = 1;
IntProperty = 1;
}
private long _numRepeat;
private object _field = null;
private object Property {get;set;}
private int IntProperty {get;set;}
public void LoopUsingBoxedGetter()
{
for (long i = 0; i < _numRepeat; i++)
{
var f = Property;
}
}
public void LoopUsingUnboxedGetter()
{
for (long i = 0; i < _numRepeat; i++)
{
var f = IntProperty;
}
}
public void LoopUsingField()
{
for (long i = 0; i < _numRepeat; i++)
{
var f = _field;
}
}
}
This produces.. ON MY MACHINE, OS X (recent version of Mono), these results (in seconds):
Using field: 2.606
Using boxed getter: 2.585
Using unboxed getter: 2.71
You say you are optimizing your code, but I am curious as to how, what the functionality is supposed to be, and what the source data coming into this is as well as it's size as this is clearly not "real" code. If you are parsing a large list of data in consider utilizing the BinarySearch functionality. This is significantly faster than, say the .Contains() function with very large sets of data.
List<int> myList = GetOrderedList();
if (myList.BinarySearch(someValue) < 0)
// List does not contain data
Perhaps you are simply looping through data. If you are looping through data and returning a value perhaps you may want to utilize the yield keyword. Additionally consider the potential use of the parallel library if you can, or utilize your own thread management.
This does not seem like what you want judging by the posted source but it was very generic so I figured this was worth mentioning.
public IEnumerable<int> LoopUsingGetter()
{
int dummy = 314;
for (int i = 0; i < NumRepet; i++)
{
dummy++;
yield return dummy;
}
}
[ThreadStatic]
private static int dummy = 314;
public static int Dummy
{
get
{
if (dummy != 314) // or whatever your condition
{
return dummy;
}
Parallel.ForEach (LoopUsingGetter(), (i)
{
//DoWork(), not ideal for given example, but due to the generic context this may help
dummy += i;
});
}
return dummy;
}
Follow the 80/20 performance rule instead of micro-optimizing.
Write code for maintainability, instead of performance.
Perhaps Assembly language is the fastest but that does not mean we should use Assembly language for all purposes.
You are running the loop 100 million times and the difference is 0.02 millisecond or 20 microseconds. Calling a function will have some overhead but in most cases it does not matter. You can trust the compiler to inline or do advanced things.
Directly accessing the field will be problematic in 99% of the cases as you will not have control of where all your variables are referenced and fixing at too many places when you find something is wrong.
You should stop the stop watch when it completes the loop, your stopwatch is still running when you are writing to console this can add additional time that can skew your results.
[Test]
public void GetterVsField()
{
PropertyTest propertyTest = new PropertyTest();
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
propertyTest.LoopUsingCopy();
stopwatch.Stop();
Console.WriteLine("Using copy: " + stopwatch.ElapsedMilliseconds / 1000.0);
stopwatch.Reset();
stopwatch.Start();
propertyTest.LoopUsingGetter();
stopwatch.Stop();
Console.WriteLine("Using getter: " + stopwatch.ElapsedMilliseconds / 1000.0);
stopwatch.Reset();
stopwatch.Start();
propertyTest.LoopUsingField();
stopwatch.Stop();
Console.WriteLine("Using field: " + stopwatch.ElapsedMilliseconds / 1000.0);
}
You have to check if optimize code checkbox is checked.
If it is not checked, access to the property is still method call
If it is checked the property is in-lined and the performance is the same as with direct field access because the JITed code will be the same
There is more restriction about inlinig in X64 JIT compiler. More information about JIT64 inlining optimization is there:
David Broman's CLR Profiling API Blog: Tail call JIT conditions.
please see point #3 The caller or callee return a value type.
If your property will return reference type, the property getter will be in-lined.
It means that the property int NumRepet { get; set; } is not inlined but object NumRepet { get; set; } will be inlined if you don't break another restriction.
The optimization of X64 JIT is poor and this is why new one will be introduced as John mention

Using == or .Equals() for bool comparison

I was reviewing some code, and I found something that looked like this:
public class MyClass
{
public bool IsEditable { get; set; }
public void HandleInput()
{
if (IsEditable.Equals(false))
{
//do stuff
}
}
}
As far as I know, (IsEditable.Equals(false)) is identical to (IsEditable == false) (and also the same as (!IsEditable)).
Besides personal preference, is there any difference at all between .Equals() and ==, specifically when used to compare bools?
This is mostly a readability issue. I'd normally use == because that's what I'm used to looking at.
Specifically with bools, you don't have to compare them at all
if(!IsEditable)
will suffice
although, Sometimes I myself do write things like if (val == false) just to be extra sure that i don't misread it when i have to modify the code.
In fact, for basic types such as int, bool etc. there is a difference between calling Equals() and == due to the fact that the CIL has instructions for handling such types. Calling Equals() forces boxing of the value and making a virtual method call, whereas usage of == leads to usage of a single CIL instruction.
!value and value == false is actually the same, at least in Microsoft's C# compiler bundled with .NET 4.0.
Hence, the comparisons within the following methods
public static int CompareWithBoxingAndVirtualMethodCall(bool value)
{
if (value.Equals(false)) { return 0; } else { return 1; }
}
public static int CompareWithCILInstruction(bool value)
{
if (value == false) { return 0; } else { return 1; }
if (!value) { return 0; } else { return 1; } // comparison same as line above
}
will compile to to the following CIL instructions:
// CompareWithBoxingAndVirtualMethodCall
ldarga.s 'value'
ldc.i4.0
call instance bool [mscorlib]System.Boolean::Equals(bool) // virtual method call
brfalse.s IL_000c // additional boolean comparison, jump for if statement
// CompareWithCILInstruction
ldarg.0
brtrue.s IL_0005 // actual single boolean comparison, jump for if statement
The Equals way appears to be significantly slower - roughly 2.7 times in debug mode, and more than seven times in release mode.
Here is my quick and dirty benchmark:
public static void Main() {
bool a = bool.Parse("false");
bool b = bool.Parse("true");
bool c = bool.Parse("true");
var sw = new Stopwatch();
const int Max = 1000000000;
int count = 0;
sw.Start();
// The loop will increment count Max times; let's measure how long it takes
for (int i = 0; i != Max; i++) {
count++;
}
sw.Stop();
var baseTime = sw.ElapsedMilliseconds;
sw.Start();
count = 0;
for (int i = 0; i != Max; i++) {
if (a.Equals(c)) count++;
if (b.Equals(c)) count++;
}
sw.Stop();
Console.WriteLine(sw.ElapsedMilliseconds - baseTime);
sw.Reset();
count = 0;
sw.Start();
for (int i = 0; i != Max; i++) {
if (a==c) count++;
if (b==c) count++;
}
sw.Stop();
Console.WriteLine(sw.ElapsedMilliseconds - baseTime);
sw.Reset();
count = 0;
sw.Start();
for (int i = 0; i != Max; i++) {
if (!a) count++;
if (!b) count++;
}
sw.Stop();
Console.WriteLine(sw.ElapsedMilliseconds - baseTime);
}
Running this produces the following results:
In debug mode
8959
2950
1874
In release mode
5348
751
7
Equals appears to be the slowest. There appears to be little difference between == and !=. However, if (!boolExpr) appears to be the clear winner.
If you decompile System.Boolean and look at it, It's Equals overloads are defined thus:
public override bool Equals(object obj)
{
if (!(obj is bool))
return false;
else
return this == (bool) obj;
}
public bool Equals(bool obj)
{
return this == obj;
}
I would like to think the C# compiler's optimizer and the .Net JIT compiler would be smart enough to inline these, at least for release/optimized compilations, making them exactly the same.
There is a difference - at least in .NET 4.8 - I believe the reason is because of the boxing described in Oliver Hanappi's answer:
static void Main(string[] args)
{
object lhs = true;
object rhs = true;
Console.WriteLine($"Are Equal - {(lhs == rhs ? "Yes" : "No")}"); // Outputs no
Console.WriteLine($"Are Equal - {(lhs.Equals(rhs) ? "Yes" : "No")}"); // Outputs yes
Console.ReadLine();
}
Take a look at the following quote Taken from here:
The Equals method is just a virtual one defined in System.Object, and
overridden by whichever classes choose to do so. The == operator is an
operator which can be overloaded by classes, but which usually has
identity behaviour.
For reference types where == has not been overloaded, it compares
whether two references refer to the same object - which is exactly
what the implementation of Equals does in System.Object.
So in short, Equals is really just doing a == anyways.
In this case, with bools, it doesn't make any difference, however with other built-in non reference types it can.
== allows for conversions of types if it can .Equals won't
== is always better than .Equals. In the case of integer comparison, == runs faster than .Equals. In the below test, the elapsed time using == 157, while for .Equals the elapsed time is 230.
class Program
{
static void Main(string[] args)
{
Program programObj = new Program();
programObj.mymethod();
programObj.mynextmethod();
}
void mynextmethod()
{
var watch = Stopwatch.StartNew();
for (int i = 0; i < 60000000; i++)
{
int j = 0;
if (i.Equals(j))
j = j + 1;
}
watch.Stop();
var elapsedMs = watch.ElapsedMilliseconds;
Console.WriteLine("Time take in method" + elapsedMs);
Console.ReadLine();
}
void mymethod()
{
var watch = Stopwatch.StartNew();
for (int i = 0; i < 60000000; i++)
{
int j = 0;
if (i == j)
j = j + 1;
}
watch.Stop();
var elapsedMs = watch.ElapsedMilliseconds;
Console.WriteLine("Time take in method" + elapsedMs);
}
}

Categories