Any easier way to write this if statement?
if (value==1 || value==2)
For example... in SQL you can say where value in (1,2) instead of where value=1 or value=2.
I'm looking for something that would work with any basic type... string, int, etc.
How about:
if (new[] {1, 2}.Contains(value))
It's a hack though :)
Or if you don't mind creating your own extension method, you can create the following:
public static bool In<T>(this T obj, params T[] args)
{
return args.Contains(obj);
}
And you can use it like this:
if (1.In(1, 2))
:)
A more complicated way :) that emulates SQL's 'IN':
public static class Ext {
public static bool In<T>(this T t,params T[] values){
foreach (T value in values) {
if (t.Equals(value)) {
return true;
}
}
return false;
}
}
if (value.In(1,2)) {
// ...
}
But go for the standard way, it's more readable.
EDIT: a better solution, according to #Kobi's suggestion:
public static class Ext {
public static bool In<T>(this T t,params T[] values){
return values.Contains(t);
}
}
C# 9 supports this directly:
if (value is 1 or 2)
however, in many cases: switch might be clearer (especially with more recent switch syntax enhancements). You can see this here, with the if (value is 1 or 2) getting compiled identically to if (value == 1 || value == 2).
Is this what you are looking for ?
if (new int[] { 1, 2, 3, 4, 5 }.Contains(value))
If you have a List, you can use .Contains(yourObject), if you're just looking for it existing (like a where). Otherwise look at Linq .Any() extension method.
Using Linq,
if(new int[] {1, 2}.Contains(value))
But I'd have to think that your original if is faster.
Alternatively, and this would give you more flexibility if testing for values other than 1 or 2 in future, is to use a switch statement
switch(value)
{
case 1:
case 2:
return true;
default:
return false
}
If you search a value in a fixed list of values many times in a long list, HashSet<T> should be used. If the list is very short (< ~20 items), List could have better performance, based on this test
HashSet vs. List performance
HashSet<int> nums = new HashSet<int> { 1, 2, 3, 4, 5 };
// ....
if (nums.Contains(value))
Generally, no.
Yes, there are cases where the list is in an Array or List, but that's not the general case.
An extensionmethod like this would do it...
public static bool In<T>(this T item, params T[] items)
{
return items.Contains(item);
}
Use it like this:
Console.WriteLine(1.In(1,2,3));
Console.WriteLine("a".In("a", "b"));
You can use the switch statement with pattern matching (another version of jules's answer):
if (value switch{1 or 3 => true,_ => false}){
// do something
}
Easier is subjective, but maybe the switch statement would be easier? You don't have to repeat the variable, so more values can fit on the line, and a line with many comparisons is more legible than the counterpart using the if statement.
In vb.net or C# I would expect that the fastest general approach to compare a variable against any reasonable number of separately-named objects (as opposed to e.g. all the things in a collection) will be to simply compare each object against the comparand much as you have done. It is certainly possible to create an instance of a collection and see if it contains the object, and doing so may be more expressive than comparing the object against all items individually, but unless one uses a construct which the compiler can explicitly recognize, such code will almost certainly be much slower than simply doing the individual comparisons. I wouldn't worry about speed if the code will by its nature run at most a few hundred times per second, but I'd be wary of the code being repurposed to something that's run much more often than originally intended.
An alternative approach, if a variable is something like an enumeration type, is to choose power-of-two enumeration values to permit the use of bitmasks. If the enumeration type has 32 or fewer valid values (e.g. starting Harry=1, Ron=2, Hermione=4, Ginny=8, Neville=16) one could store them in an integer and check for multiple bits at once in a single operation ((if ((thisOne & (Harry | Ron | Neville | Beatrix)) != 0) /* Do something */. This will allow for fast code, but is limited to enumerations with a small number of values.
A somewhat more powerful approach, but one which must be used with care, is to use some bits of the value to indicate attributes of something, while other bits identify the item. For example, bit 30 could indicate that a character is male, bit 29 could indicate friend-of-Harry, etc. while the lower bits distinguish between characters. This approach would allow for adding characters who may or may not be friend-of-Harry, without requiring the code that checks for friend-of-Harry to change. One caveat with doing this is that one must distinguish between enumeration constants that are used to SET an enumeration value, and those used to TEST it. For example, to set a variable to indicate Harry, one might want to set it to 0x60000001, but to see if a variable IS Harry, one should bit-test it with 0x00000001.
One more approach, which may be useful if the total number of possible values is moderate (e.g. 16-16,000 or so) is to have an array of flags associated with each value. One could then code something like "if (((characterAttributes[theCharacter] & chracterAttribute.Male) != 0)". This approach will work best when the number of characters is fairly small. If array is too large, cache misses may slow down the code to the point that testing against a small number of characters individually would be faster.
Using Extension Methods:
public static class ObjectExtension
{
public static bool In(this object obj, params object[] objects)
{
if (objects == null || obj == null)
return false;
object found = objects.FirstOrDefault(o => o.GetType().Equals(obj.GetType()) && o.Equals(obj));
return (found != null);
}
}
Now you can do this:
string role= "Admin";
if (role.In("Admin", "Director"))
{
...
}
public static bool EqualsAny<T>(IEquatable<T> value, params T[] possibleMatches) {
foreach (T t in possibleMatches) {
if (value.Equals(t))
return true;
}
return false;
}
public static bool EqualsAny<T>(IEquatable<T> value, IEnumerable<T> possibleMatches) {
foreach (T t in possibleMatches) {
if (value.Equals(t))
return true;
}
return false;
}
I had the same problem but solved it with a switch statement
switch(a value you are switching on)
{
case 1:
the code you want to happen;
case 2:
the code you want to happen;
default:
return a value
}
Related
I've got a enum type defined in my C# code that corresponds to all possible values for the NetConnectionStatus field in Win32_NetworkAdapter WMI table, as documented here.
The documentation shows that the integers 0 through 12 each have a unique status name, but then all integers between 13 and 65,535 are lumped into one bucket called "Other." So here's my code:
[Serializable]
public enum NetConnectionStatus
{
Disconnected = 0,
Connecting = 1,
Connected = 2,
Disconnecting = 3,
HardwareNotPresent = 4,
HardwareDisabled = 5,
HardwareMalfunction = 6,
MediaDisconnected = 7,
Authenticating = 8,
AuthenticationSucceeded = 9,
AuthenticationFailed = 10,
InvalidAddress = 11,
CredentialsRequired = 12,
Other
}
This works fine for the values that are not Other. For instance, I can do this:
var result = (NetConnectionStatus) 2;
Assert.AreEqual(NetConnectionStatus.Connected, result);
But for anything in that higher numeric range, it doesn't work so great. I would like it if I could do this:
var result = (NetConnectionStatus) 20;
Assert.AreEqual(NetConnectionStatus.Other, result);
But right now that result variable gets assigned the literal value 20 instead of Other. Is there some out-of-the-box way of accomplishing this, something akin to Parse() but for integers instead of strings, or perhaps some special attribute I'm unaware of? I would prefer to not write my own wrapper method for this if there is already a good way to accomplish this.
If you have a string value, then the closest thing I can think of is to use Enum.TryParse:
NetConnectionStatus result;
if (Enum.TryParse(stringValue, out result) == false)
result = NetConnectionStatus.Other;
For an integer value that you're casting, you can use:
result = (NetConnectionStatus)integerValue;
if (Enum.GetValues(typeof(NetConnectionStatus)).Contains(result) == false)
result = NetConnectionStatus.Other;
Not really ideal, but in C# enums aren't much more than fancy names for integral values, so it's valid to stuff an integer value not in the defined values of the enums into a value of that enum type.
This solution will handle negative numbers, or cases where you have gaps in your enum values more elegantly than doing numerical comparisons.
it would be nice but no. How about
var result = (NetConnectionStatus) 20;
Assert.IsTrue(result >= (int)NetConnectionStatus.Other);
.NET does not such thing as a "any other" enumeration value bucket. Technically, enumeration (enum) is a pretty set of named constants of some underlying type (which is one of following: sbyte, short, int, long and their unsigned counterparts). You can cast an enum value to/from a corresponding type without any losses, as in this example:
enum TestEnum:int // Explicitly stating a type.
{
OnlyElement=0
}
class Program
{
static void Main(string[] args)
{
// Console.WriteLine implicitly calls ToString of the TestEnum.OnlyElement.
Console.WriteLine("OnlyElement == {0}", TestEnum.OnlyElement);
//TestEnum.OnlyElement equals to 0, as demonstrated by this casting:
Console.WriteLine("(int)OnlyElement == {0}", (int)TestEnum.OnlyElement);
//We can do it in reverse...
Console.WriteLine("(TestEnum)0 == ",(TestEnum)0);
// But what happens when we try to cast a value, which is not
// representable by any of enum's named constants,
// into value of enum in question? No exception is thrown
// whatsoever: enum variable simply holds that value, and,
// having no named constant to associate it with, simply returns
// that value when attempting to "ToString"ify it:
Console.WriteLine("(TestEnum)5 == {0}", (TestEnum)5); //prints "(TestEnum)5 == 5".
Console.ReadKey();
}
}
I'd like to repeat it again, enum in .NET is simply a value of the underlying type with some nice decorations like overriden ToString method and flags checking (look here or here if you want to know more about flags). You cannot have an integer with only 14 values like "0..12 and everything else", and so you cannot have such enum. In your example, NetConnectionStatus.Other simply receives single literal value (I assume it would most probably be '13', as the next available positive value of underlying type - however it actually depends on the compiler) as any other enumeration constant would do if not specified explicitly - and, obviously, it does not become a bucket.
However, there are options to achieve simple equation checks for integers/bytes/shorts/longs - and enums alike. Consider this extension method:
static bool IsOther(this NetConnectionStatus A)
{
return (A < (NetConnectionStatus)0) || (A > (NetConnectionStatus)12);
}
Now you can have a simple assertion like this:
var result = (NetConnectionStatus)10;
Trace.Assert(result.IsOther()); //No assertion is triggered; result is NetConnectionStatus.AuthenticationFailed
and
var result = (NetConnectionStatus)20;
Trace.Assert(result.IsOther()); //Assertion failed; result is undefined!
(Of course you can replace IsOther method with IsNotOther, overload it and pretty much anything else you could do with a method.)
Now there is one more thing. Enum class itself contains a method called IsDefined, which allows you to avoid checks for specific enum's value boundaries (<0, >12), therefore preventing unwanted bugs in case enum values would ever be added/removed, at the small performance cost of unboxing and checking each value in enum for a match (I'm not sure how this works under the hood though, I hope these checks are optimized). So your method would look like this:
static bool IsOther(NetConnectionStatus A)
{
return !Enum.IsDefined(typeof(NetConnectionStatus), A);
}
(However, concluding from enum's name, it seems like you want to make a network application/server, and for these performance might be of very great importance - but most probably I'm just being paranoid and this will not be your application's bottleneck. Stability is much more of concern, and, unless you experience real troubles with performance, it is considered to be much better practice to enable as much stability&safety&portability as possible. Enum.IsDefined is much more understandable, portable and stable than the explicit boundaries checking.)
Hope that helps!
Thanks everyone for the replies. As confirmed by all of you, there is indeed no way to do this out-of-the-box. For the benefit of others I thought I'd post the (custom) code I ended up writing. I wrote an extension method that utilizes a custom attribute on the enum value that I called [CatchAll].
public class CatchAll : Attribute { }
public static class EnumExtensions
{
public static T ToEnum<T, U>(this U value) where T : struct, IConvertible where U : struct, IComparable, IConvertible, IFormattable, IComparable<U>, IEquatable<U>
{
var result = (T)Enum.ToObject(typeof(T), value);
var values = Enum.GetValues(typeof(T)).Cast<T>().ToList();
if (!values.Contains(result))
{
foreach (var enumVal in from enumVal in values
let info = typeof(T).GetField(enumVal.ToString())
let attrs = info.GetCustomAttributes(typeof(CatchAll), false)
where attrs.Length == 1
select enumVal)
{
result = enumVal;
break;
}
}
return result;
}
}
So then I just have to apply that [CatchAll] attribute to the Other value in the enum definition. Then I can do things like this:
int value = 13;
var result = value.ToEnum<NetConnectionStatus, int>();
Assert.AreEqual(NetConnectionStatus.Other, result);
And this:
ushort value = 20;
result = value.ToEnum<NetConnectionStatus, ushort>();
Assert.AreEqual(NetConnectionStatus.Other, result);
I have two methods in an IntExtensions class to help generate the next available incremental value (which is not in a list of existing integers which need to be excluded).
I dont think I'm addressing the NextIncrementalValueNotInList method in the best way and am wondering if I can better use linq to return the next available int?
public static bool IsInList(this int value, List<int> ListOfIntegers) {
if (ListOfIntegers.Contains(value))
return true;
return false;
}
public static int NextIncrementalValueNotInList(this int value,
List<int> ListOfIntegers) {
int maxResult;
maxResult = ListOfIntegers.Max() + 1;
for (int i = value; i <= maxResult; i++)
{
if (!(i.IsInList(ListOfIntegers)))
{
return i;
}
}
return maxResult;
}
Using linq your method will look like:
return IEnumerable.Range(1, ListOfIntegers.Count + 1)
.Except(ListOfIntegers)
.First();
I guess it starting at 1.
You could also proceed like this:
IEnumerable.Range(1, ListOfIntegers.Count)
.Where(i => !ListOfIntegers.Contains(i))
.Union(new []{ ListOfIntegers.Count + 1 })
.First();
You don't actually need to calculate the Max value - just keep incrementing i until you find a value that doesn't exist in the list, e.g:
public static int NextIncrementalValueNotInList(this int value,
List<int> ListOfIntegers)
{
int i = value;
while(true)
{
if (!(i.IsInList(ListOfIntegers)))
{
return i;
}
i++;
}
return maxResult;
}
. Besides that, I'm not sure if there's much more you can do about this unless:
ListOfIntegers is guaranteed to be, or needs to be, sorted, or
ListOfIntegers doesn't actually need to be a List<int>
If the answer to the first is no, and to the second is yes, then you might instead use a HashSet<int>, which might provide a faster implementation by allowing you to simply use HashSet<T>'s own bool Contains(T) method:
public static int NextIncrementalValueNotInList(this int value,
HashSet<int> ListOfIntegers)
{
int i = value;
while(true)
{
if (!(ListOfIntegers.Contains(i))
{
return value;
}
i++;
}
}
Note that this version shows how to do away with the Max check also.
Although be careful of premature optimisation - if your current implementation is fast enough, then I wouldn't worry. You should properly benchmark any alternative solution with extreme cases as well as real-world cases to see if there's actually any difference.
Also what you don't want to do is use my suggestion above by turning your list into a HashSet for every call. I'm suggesting changing entirely your use of List to HashSet - any piecemeal conversion per-call will negate any potential performance benefits due to the overhead of creating the HashSet.
Finally, if you're not actually expecting much fragmentation in your integer list, then it's possible that a HashSet might not be much different from the current Linq version, because it's possibly going to end up doing similar amounts of work anyway.
I understood that when using Regex I can enter the value | to search for many values. For example:
Regex sabrina = new Regex("Rihanna|rihanna|Sabrina|sabrina");
I have a string which I want to compare to other values, so I use if like this:
if (rihanna == "Rihanna" || rihanna == "sabrina")
My question is if it possible to make the if shorter? I know this code is not working but what I'm looking for something like this:
if (rihanna == "Rihanna|sabrina")
Single line solution:
if("Rihanna|rihanna|Sabrina|sabrina".Split(new[] {'|'}).Contains(rihanna))
or without String.Split method usage:
if ((new[] { "Rihanna", "rihanna", "Sabrina", "sabrina" }).Contains(rihanna))
If that kind of check is performed more than once you should save string[] array of possible values into a variable:
var names = new[] { "Rihanna", "rihanna", "Sabrina", "sabrina" };
if(names.Contains(rihanna))
You could use a List<string> along with the Enumerable.Contains method.
Example:
var values = new List<string> { "Rihanna", "rihanna", "Sabrina", "sabrina" };
if (values.Contains(rihanna))
{
// etc.
}
The if statement is now a lot more concise, and you can add more items to your list quickly and easily. If you're performing this operation frequently, you should move the declaration of the list to a member variable in the containing class so that you don't incur the overhead of list initialization every time this method is called.
An even better solution would be to use Enumerable.Any and String.Equals to perform a case-insensitive comparison:
if (values.Any(x => String.Equals(rihanna, x, StringComparison.OrdinalIgnoreCase))
{
// your code here
}
Although the if statement is now longer, the solution is much more robust.
If you're looking for easier maintenance of a potentially long list of string candidates, why not use a switch statement? Technically it will be "longer" character-wise, but if you have to modify things down the road, or provide some subtle secondary processing, it could make things a lot easier.
As an alternative to the above answers, perhaps you could consider using an extension method:
public static bool EqualsAny(this string input, params string[] values)
{
return values.Any(v => String.Equals(input, v, StringComparison.OrdinalIgnoreCase));
}
With usage like:
if (rihanna.EqualsAny("Rihanna", "Sabrina"))
This should give pretty readable/compact/short if comparisons for you, especially in comparison to some of the other alternatives here.
Tweak the EqualsAny check if you want to have the OrdinalIgnoreCase or not or feel free to add any overloads you wish. Could even implement the whole piping/splitting where you'd pass in "Rihanna|Sabrina".
EDIT: Perhaps more critically, it centralizes how you compare rather than duplicating the code everywhere.
You can use your own Regex and use it as a single line..
if (Regex.Match(rihanna, "Rihanna|rihanna|Sabrina|sabrina").Success)
Or make it case-insensative like this..
if (Regex.Match(rihanna, "rihanna|sabrina", RegexOptions.IgnoreCase).Success){
Ignore casing, which looks like something you're going for, and use String.Compare:
if(String.Compare(rihanna, "sabrina", StringComparison.OrdinalIgnoreCase) == 0 ||
String.Compare(rihanna, "rihana", StringComparison.OrdinalIgnoreCase) == 0 ) {
// do stuff
}
Dictionary or HashSet (potentially with case insensitive check on names) is another approach which will give you better performance if you have more than several items and repeat checks often.
var listToCheck = new Dictionary<string, string>(
StringComparer.CurrentCultureIgnoreCase) { { "rihanna", null}};
if (listToCheck.ContainsKey("Rihanna")) ....
I'm trying to find a solution to this problem:
Given a IEnumerable< IEnumerable< int>> I need a method/algorithm that returns the input, but in case of several IEnmerable< int> with the same elements only one per coincidence/group is returned.
ex.
IEnumerable<IEnumerable<int>> seqs = new[]
{
new[]{2,3,4}, // #0
new[]{1,2,4}, // #1 - equals #3
new[]{3,1,4}, // #2
new[]{4,1,2} // #3 - equals #1
};
"foreach seq in seqs" .. yields {#0,#1,#2} or {#0,#2,#3}
Sould I go with ..
.. some clever IEqualityComparer
.. some clever LINQ combination I havent figured out - groupby, sequenceequal ..?
.. some seq->HashSet stuff
.. what not. Anything will help
I'll be able to solve it by good'n'old programming but inspiration is always appreciated.
Here's a slightly simpler version of digEmAll's answer:
var result = seqs.Select(x => new HashSet<int>(x))
.Distinct(HashSet<int>.CreateSetComparer());
Given that you want to treat the elements as sets, you should have them that way to start with, IMO.
Of course this won't help if you want to maintain order within the sequences that are returned, you just don't mind which of the equal sets is returned... the above code will return an IEnumerable<HashSet<int>> which will no longer have any ordering within each sequence. (The order in which the sets are returned isn't guaranteed either, although it would be odd for them not to be return in first-seen-first-returned basis.)
It feels unlikely that this wouldn't be enough, but if you could give more details of what you really need to achieve, that would make it easier to help.
As noted in comments, this will also assume that there are no duplicates within each original source array... or at least, that they're irrelevant, so you're happy to treat { 1 } and { 1, 1, 1, 1 } as equal.
Use the correct collection type for the job. What you really want is ISet<IEnumerable<int>> with an equality comparer that will ignore the ordering of the IEnumerables.
EDITED:
You can get what you want by building your own IEqualityComparer<IEnumerable<int>> e.g.:
public class MyEqualityComparer : IEqualityComparer<IEnumerable<int>>
{
public bool Equals(IEnumerable<int> x, IEnumerable<int> y)
{
return x.OrderBy(el1 => el1).SequenceEqual(y.OrderBy(el2 => el2));
}
public int GetHashCode(IEnumerable<int> elements)
{
int hash = 0;
foreach (var el in elements)
{
hash = hash ^ el.GetHashCode();
}
return hash;
}
}
Usage:
var values = seqs.Distinct(new MyEqualityComparer()).ToList();
N.B.
this solution is slightly different from the one given by Jon Skeet.
His answer considers sublists as sets, so basically two lists like [1,2] and [1,1,1,2,2] are equal.
This solution don't, i.e. :
[1,2,1,1] is equal to [2,1,1,1] but not to [2,2,1,1], hence basically the two lists have to contain the same elements and in the same number of occurrences.
Which is faster? This:
bool isEqual = (MyObject1 is MyObject2)
Or this:
bool isEqual = ("blah" == "blah1")
It would be helpful to figure out which one is faster. Obviously, if you apply .ToUpper() to each side of the string comparison like programmers often do, that would require reallocating memory which affects performance. But how about if .ToUpper() is out of the equation like in the above sample?
I'm a little confused here.
As other answers have noted, you're comparing apples and oranges. ::rimshot::
If you want to determine if an object is of a certain type use the is operator.
If you want to compare strings use the == operator (or other appropriate comparison method if you need something fancy like case-insensitive comparisons).
How fast one operation is compared to the other (no pun intended) doesn't seem to really matter.
After closer reading, I think that you want to compare the speed of string comparisions with the speed of reference comparisons (the type of comparison used in the System.Object base type).
If that's the case, then the answer is that reference comparisons will never be slower than any other string comparison. Reference comparison in .NET is pretty much analogous to comparing pointers in C - about as fast as you can get.
However, how would you feel if a string variable s had the value "I'm a string", but the following comparison failed:
if (((object) s) == ((object) "I'm a string")) { ... }
If you simply compared references, that might happen depending on how the value of s was created. If it ended up not being interned, it would not have the same reference as the literal string, so the comparison would fail. So you might have a faster comparison that didn't always work. That seems to be a bad optimization.
According to the book Maximizing .NET Performance
the call
bool isEqual = String.Equals("test", "test");
is identical in performance to
bool isEqual = ("test" == "test");
The call
bool isEqual = "test".Equals("test");
is theoretically slower than the call to the static String.Equals method, but I think you'll need to compare several million strings in order to actually detect a speed difference.
My tip to you is this; don't worry about which string comparison method is slower or faster. In a normal application you'll never ever notice the difference. You should use the way which you think is most readable.
The first one is used to compare types not values.
If you want to compare strings with a non-sensitive case you can use:
string toto = "toto";
string tata = "tata";
bool isEqual = string.Compare(toto, tata, StringComparison.InvariantCultureIgnoreCase) == 0;
Console.WriteLine(isEqual);
How about you tell me? :)
Take the code from this Coding Horror post, and insert your code to test in place of his algorithm.
Comparing strings with a "==" operator compares the contents of the string vs. the string object reference. Comparing objects will call the "Equals" method of the object to determine whether they are equal or not. The default implementation of Equals is to do a reference comparison, returning True if both object references are the same physical object. This will likely be faster than the string comparison, but is dependent on the type of object being compared.
I'd assume that comparing the objects in your first example is going to be about as fast as it gets since its simply checking if both objects point to the same address in memory.
As it has been mentioned several times already, it is possible to compare addresses on strings as well, but this won't necessarily work if the two strings are allocated from different sources.
Lastly, its usually good form to try and compare objects based on type whenever possible. Its typically the most concrete method of identification. If your objects need to be represented by something other than their address in memory, its possible to use other attributes as identifiers.
If I understand the question and you really want to compare reference equality with the plain old "compare the contents": Build a testcase and call object.ReferenceEquals compared against a == b.
Note: You have to understand what the difference is and that you probably cannot use a reference comparison in most scenarios. If you are sure that this is what you want it might be a tiny bit faster. You have to try it yourself and evaluate if this is worth the trouble at all..
I don't feel like any of these answers address the actual question. Let's say the string in this example is the type's name and we're trying to see if it's faster to compare a type name or the type to determine what it is.
I put this together and to my surprise, it's about 10% faster to check the type name string than the type in every test I ran. I intentionally put the simplest strings and classes into play to see if it was possible to be faster, and turns out it is possible. Not sure about more complicated strings and type comparisons from heavily inherited classes. This is of course a micro-op and may possibly change at some point in the evolution of the language I suppose.
In my case, I was considering a value converter that switches based on this name, but it could also switch over the type since each type specifies a unique type name. The value converter would figure out the font awesome icon to show based on the type of item presented.
using System;
using System.Diagnostics;
using System.Linq;
namespace ConsoleApp1
{
public sealed class A
{
public const string TypeName = "A";
}
public sealed class B
{
public const string TypeName = "B";
}
public sealed class C
{
public const string TypeName = "C";
}
class Program
{
static void Main(string[] args)
{
var testlist = Enumerable.Repeat(0, 100).SelectMany(x => new object[] { new A(), new B(), new C() }).ToList();
int count = 0;
void checkTypeName()
{
foreach (var item in testlist)
{
switch (item)
{
case A.TypeName:
count++;
break;
case B.TypeName:
count++;
break;
case C.TypeName:
count++;
break;
default:
break;
}
}
}
void checkType()
{
foreach (var item in testlist)
{
switch (item)
{
case A _:
count++;
break;
case B _:
count++;
break;
case C _:
count++;
break;
default:
break;
}
}
}
Stopwatch sw = Stopwatch.StartNew();
for (int i = 0; i < 100000; i++)
{
checkTypeName();
}
sw.Stop();
Console.WriteLine(sw.Elapsed);
sw.Restart();
for (int i = 0; i < 100000; i++)
{
checkType();
}
sw.Stop();
Console.WriteLine(sw.Elapsed);
}
}
}