Often you want to send multiple values but due to low use (i.e. it is only used in one or two places), it's hard to justify creating a new type.
The Tuple<...> and KeyValuePair<,> type are very useful, but there isn't real language support for them.
Well sort of, a nice trick to use for Lists of tuples is to create a type that extends the List and adding a custom add method:
e.g.
public class TupleList<T1,T2> : List<Tuple<T1,T2>>{
public void Add(T1 key, T2 value){
base.Add(Tuple.Create(key, value));
}
}
This means that if I have a method that takes an IEnumerable<Tuple<int,string>>, I can use the following code to quickly build up the list like so::
Foo(new TupleList<int,string>{{1,"one"},{2,"two"},{3,"three"}});
This makes winding values into a tuple list easier as we don't have to constantly keep saying Tuple.Create, and gets us almost to a nice functional languages syntax.
But when working with a tuple it is useful to unwind it out into its different components. This extension method might be useful in this respect::
public static void Unwind<T1,T2>(this Tuple<T1,T2> tuple,out T1 var1,out T2 var2)
{
var1 = tuple.Item1;
var2 = tuple.Item2;
}
But even that's annoying as out parameters are not variant at all. That is if T1 is a string, I can't send in an object variable even though they are assignable, when as I can do the unwinding by hand otherwise. I can't really suggest a reason why you might want this variance, but if its there, I can't see why you would want to lose it.
Anyone have other tips to making working tuples, or tuple like objects easier in C#?
An important potential use for tuples might be generic memoization. Which is very easy in languages like F#, but hard in C#.
I'm currently using Tuples to supply a MethodBase and an array of tokens (constants, objects, or argument tokens), supplied to a dynamicly built object to construct certain member fields.
Since I wanted to make the syntax easier on API consumers, I created Add methods that can take a ConstructorInfo or a MethodInfo and a params array of objects.
Edit:
Eric Lippert as usual has excellent motivation for using Tuples here and he even says what I suspected there really is no support:
What requirement was the tuple designed to solve?
In C# you can alias closed generic types, which Tuple is, this enables you to provide some better insight to what is intended. Doesn't change code much, but if you look at the example below the intent of what GetTemp is returning is better.
Without alias:
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
var result = GetTemp(10, 10);
Console.WriteLine("Temp for {0} is {1}", result.Item2, result.Item1);
}
// You give a lat & a long and you get the closest city & temp for it
static Tuple<double, string> GetTemp(double lat, double #long)
{
// just for example
return Tuple.Create(10d, "Mordor");
}
}
}
With alias:
namespace ConsoleApplication1
{
using CityTemp = Tuple<double, string>;
class Program
{
static void Main(string[] args)
{
var result = GetTemp(10, 10);
Console.WriteLine("Temp for {0} is {1}", result.Item2, result.Item1);
}
// You give a lat & a long and you get the closest city & temp for it
static CityTemp GetTemp(double lat, double #long)
{
// just for example
return new CityTemp(10, "Mordor");
}
}
}
Use Mono! They have experimental support for binding variables to tuple members so you could call a method like
Tuple<string, string, string, int, string> ParseUri (string url);
using code like
(user, password, host, port, path) = ParseUri (url);
There will be an awesome tuple feature coming with c#7 / visual studio 15.
basically you can do soething like that
static (int x, int y) DoSomething()
{
return (1, 2);
}
static void Test()
{
var cool = DoSomething();
var value = cool.x;
}
Read according post
Related
One of the nice new features of C# 7 is the possibility to define deconstructors for classes and assign the deconstructed values directly to a value tuple.
However, in the case that the object is deconstructed into a single value, I can't find a way to assign it to a tuple. Although there is a type for tuples with a single element (ValueTuple<T>), the shorthand syntax using parentheses doesn't work here. The only way I found to access the deconstructor was to call the Deconstruct method directly, but this eliminates its benefit, as I could use any method for this end.
Does anyone know a better way to deconstruct an object into a single value?
Here is my test code:
class TestClass
{
private string s;
private int n;
public TestClass(string s, int n) => (this.s, this.n) = (s, n);
public void Deconstruct(out string s) => s = this.s;
public void Deconstruct(out string s, out int n) => (s, n) = (this.s, this.n);
}
static void Main(string[] args)
{
var testObject = new TestClass("abc", 3);
var (s1) = testObject; // sytax error (comma expected)
ValueTuple<string> t = testObject; // error: "no implicit conversion from TestClass to (string)"
testObject.Deconstruct(out string s2); // this works
var (s3, n) = testObject; // no problem
Console.WriteLine($"{s1} {t.Item1} {s2} {s3} {n}");
Console.ReadKey();
}
Although there is a type for tuples with a single element (ValueTuple<T>), the shorthand syntax using parentheses doesn't work here.
That's correct. The tuple syntax only works for tuples of 2 values or more, so the Deconstruct method with only one out parameter is not very useful. (There is even a ValueTuple type for 0 elements)
The shortest solution is to just ignore the 2nd parameter:
var (s1, _) = testObject;
Edit: based on comments, a little clarification.
As of C# 7, _ is no longer a variable in this situation. It is a new feature called 'discard'.
Even if you have multiple out parameters (and even if they are different types) you can ignore any of them with an underscore:
var (s1, _, _, _) = testObject;
Deconstructions into a single element are not supported in C# 7.0.
It is unclear why you would need such a mechanism, as you can simply access a property or write a conversion operator to achieve the same thing.
Conceptually, a tuple of one element is just that one element (you don't need a tuple to hold it). So there is no tuple syntax (using parentheses notation) to facilitate that (not to mention it would be syntactically ambiguous). The same applies for deconstructions.
Here are the most relevant LDM notes I could find: 2017-03-15 (zero and one element tuples and deconstructions).
It is possible that such deconstruction could become allowed in some future recursive pattern scenarios, but that has not been finalized yet.
I was doing some speed tests and I noticed that Enum.HasFlag is about 16 times slower than using the bitwise operation.
Does anyone know the internals of Enum.HasFlag and why it is so slow? I mean twice as slow wouldn't be too bad but it makes the function unusable when its 16 times slower.
In case anyone is wondering, here is the code I am using to test its speed.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
namespace app
{
public class Program
{
[Flags]
public enum Test
{
Flag1 = 1,
Flag2 = 2,
Flag3 = 4,
Flag4 = 8
}
static int num = 0;
static Random rand;
static void Main(string[] args)
{
int seed = (int)DateTime.UtcNow.Ticks;
var st1 = new SpeedTest(delegate
{
Test t = Test.Flag1;
t |= (Test)rand.Next(1, 9);
if (t.HasFlag(Test.Flag4))
num++;
});
var st2 = new SpeedTest(delegate
{
Test t = Test.Flag1;
t |= (Test)rand.Next(1, 9);
if (HasFlag(t , Test.Flag4))
num++;
});
rand = new Random(seed);
st1.Test();
rand = new Random(seed);
st2.Test();
Console.WriteLine("Random to prevent optimizing out things {0}", num);
Console.WriteLine("HasFlag: {0}ms {1}ms {2}ms", st1.Min, st1.Average, st1.Max);
Console.WriteLine("Bitwise: {0}ms {1}ms {2}ms", st2.Min, st2.Average, st2.Max);
Console.ReadLine();
}
static bool HasFlag(Test flags, Test flag)
{
return (flags & flag) != 0;
}
}
[DebuggerDisplay("Average = {Average}")]
class SpeedTest
{
public int Iterations { get; set; }
public int Times { get; set; }
public List<Stopwatch> Watches { get; set; }
public Action Function { get; set; }
public long Min { get { return Watches.Min(s => s.ElapsedMilliseconds); } }
public long Max { get { return Watches.Max(s => s.ElapsedMilliseconds); } }
public double Average { get { return Watches.Average(s => s.ElapsedMilliseconds); } }
public SpeedTest(Action func)
{
Times = 10;
Iterations = 100000;
Function = func;
Watches = new List<Stopwatch>();
}
public void Test()
{
Watches.Clear();
for (int i = 0; i < Times; i++)
{
var sw = Stopwatch.StartNew();
for (int o = 0; o < Iterations; o++)
{
Function();
}
sw.Stop();
Watches.Add(sw);
}
}
}
}
Results:
HasFlag: 52ms 53.6ms 55ms
Bitwise: 3ms 3ms 3ms
Does anyone know the internals of Enum.HasFlag and why it is so slow?
The actual check is just a simple bit check in Enum.HasFlag - it's not the problem here. That being said, it is slower than your own bit check...
There are a couple of reasons for this slowdown:
First, Enum.HasFlag does an explicit check to make sure that the type of the enum and the type of the flag are both the same type, and from the same Enum. There is some cost in this check.
Secondly, there is an unfortunate box and unbox of the value during a conversion to UInt64 that occurs inside of HasFlag. This is, I believe, due to the requirement that Enum.HasFlag work with all enums, regardless of the underlying storage type.
That being said, there is a huge advantage to Enum.HasFlag - it's reliable, clean, and makes the code very obvious and expressive. For the most part, I feel that this makes it worth the cost - but if you're using this in a very performance critical loop, it may be worth doing your own check.
Decompiled code of Enum.HasFlags() looks like this:
public bool HasFlag(Enum flag)
{
if (!base.GetType().IsEquivalentTo(flag.GetType()))
{
throw new ArgumentException(Environment.GetResourceString("Argument_EnumTypeDoesNotMatch", new object[] { flag.GetType(), base.GetType() }));
}
ulong num = ToUInt64(flag.GetValue());
return ((ToUInt64(this.GetValue()) & num) == num);
}
If I were to guess, I would say that checking the type was what's slowing it down most.
Note that in recent versions of .Net Core, this has been improved and Enum.HasFlag compiles to the same code as using bitwise comparisons.
The performance penalty due to boxing discussed on this page also affects the public .NET functions Enum.GetValues and Enum.GetNames, which both forward to (Runtime)Type.GetEnumValues and (Runtime)Type.GetEnumNames respectively.
All of these functions use a (non-generic) Array as a return type--which is not so bad for the names (since String is a reference type)--but is quite inappropriate for the ulong[] values.
Here's a peek at the offending code (.NET 4.7):
public override Array /* RuntimeType.*/ GetEnumValues()
{
if (!this.IsEnum)
throw new ArgumentException();
ulong[] values = Enum.InternalGetValues(this);
Array array = Array.UnsafeCreateInstance(this, values.Length);
for (int i = 0; i < values.Length; i++)
{
var obj = Enum.ToObject(this, values[i]); // ew. boxing.
array.SetValue(obj, i); // yuck
}
return array; // Array of object references, bleh.
}
We can see that prior to doing the copy, RuntimeType goes back again to System.Enum to get an internal array, a singleton which is cached, on demand, for each specific Enum. Notice also that this version of the values array does use the proper strong signature, ulong[].
Here's the .NET function (again we're back in System.Enum now). There's a similar function for getting the names (not shown).
internal static ulong[] InternalGetValues(RuntimeType enumType) =>
GetCachedValuesAndNames(enumType, false).Values;
See the return type? This looks like a function we'd like to use... But first consider that a second reason that .NET re-copys the array each time (as you saw above) is that .NET must ensure that each caller gets an unaltered copy of the original data, given that a malevolent coder could change her copy of the returned Array, introducing a persistent corruption. Thus, the re-copying precaution is especially intended to protect the cached internal master copy.
If you aren't worried about that risk, perhaps because you feel confident you won't accidentally change the array, or maybe just to eke-out a few cycles of (what's surely premature) optimization, it's simple to fetch the internal cached array copy of the names or values for any Enum:
→ The following two functions comprise the sum contribution of this article ←
→ (but see edit below for improved version) ←
static ulong[] GetEnumValues<T>() where T : struct =>
(ulong[])typeof(System.Enum)
.GetMethod("InternalGetValues", BindingFlags.Static | BindingFlags.NonPublic)
.Invoke(null, new[] { typeof(T) });
static String[] GetEnumNames<T>() where T : struct =>
(String[])typeof(System.Enum)
.GetMethod("InternalGetNames", BindingFlags.Static | BindingFlags.NonPublic)
.Invoke(null, new[] { typeof(T) });
Note that the generic constraint on T isn't fully sufficient for guaranteeing Enum. For simplicity, I left off checking any further beyond struct, but you might want to improve on that. Also for simplicity, this (ref-fetches and) reflects directly off the MethodInfo every time rather than trying to build and cache a Delegate. The reason for this is that creating the proper delegate with a first argument of non-public type RuntimeType is tedious. A bit more on this below.
First, I'll wrap up with usage examples:
var values = GetEnumValues<DayOfWeek>();
var names = GetEnumNames<DayOfWeek>();
and debugger results:
'values' ulong[7]
[0] 0
[1] 1
[2] 2
[3] 3
[4] 4
[5] 5
[6] 6
'names' string[7]
[0] "Sunday"
[1] "Monday"
[2] "Tuesday"
[3] "Wednesday"
[4] "Thursday"
[5] "Friday"
[6] "Saturday"
So I mentioned that the "first argument" of Func<RuntimeType,ulong[]> is annoying to reflect over. However, because this "problem" arg happens to be first, there's a cute workaround where you can bind each specific Enum type as a Target of its own delegate, where each is then reduced to Func<ulong[]>.)
Clearly, its pointless to make any of those delegates, since each would just be a function that always return the same value... but the same logic seems to apply, perhaps less obviously, to the original situation as well (i.e., Func<RuntimeType,ulong[]>). Although we do get by with a just one delegate here, you'd never really want to call it more than once per Enum type. Anyway, all of this leads to a much better solution, which is included in the edit below.
[edit:]Here's a slightly more elegant version of the same thing. If you will be calling the functions repeatedly for the same Enum type, the version shown here will only use reflection one time per Enum type. It saves the results in a locally-accessible cache for extremely rapid access subsequently.
static class enum_info_cache<T> where T : struct
{
static _enum_info_cache()
{
values = (ulong[])typeof(System.Enum)
.GetMethod("InternalGetValues", BindingFlags.Static | BindingFlags.NonPublic)
.Invoke(null, new[] { typeof(T) });
names = (String[])typeof(System.Enum)
.GetMethod("InternalGetNames", BindingFlags.Static | BindingFlags.NonPublic)
.Invoke(null, new[] { typeof(T) });
}
public static readonly ulong[] values;
public static readonly String[] names;
};
The two functions become trivial:
static ulong[] GetEnumValues<T>() where T : struct => enum_info_cache<T>.values;
static String[] GetEnumNames<T>() where T : struct => enum_info_cache<T>.names;
The code shown here illustrates a pattern of combining three specific tricks that seem to mutually result in an unusualy elegant lazy caching scheme. I've found the particular technique to have surprisingly wide application.
using a generic static class to cache independent copies of the arrays for each distinct Enum. Notably, this happens automatically and on demand;
related to this, the loader lock guarantees unique atomic initialization and does this without the clutter of conditional checking constructs. We can also protect static fields with readonly (which, for obvious reasons, typically can't be used with other lazy/deferred/demand methods);
finally, we can capitalize on C# type inference to automatically map the generic function (entry point) into its respective generic static class, so that the demand caching is ultimately even driven implicitly (viz., the best code is the code that isn't there--since it can never have bugs)
You probably noticed that the particular example shown here doesn't really illustrate point (3) very well. Rather than relying on type inference, the void-taking function has to manually propagate forward the type argument T. I didn't choose to expose these simple functions such that there would be an opportunity to show how C# type inference makes the overall technique shine...
However, you can imagine that when you do combine a static generic function that can infer its type argument(s)--i.e., so you don't even have to provide them at the call site--then it gets quite powerful.
The key insight is that, while generic functions have the full type-inference capability, generic classes do not, that is, the compiler will never infer T if you try to call the first of the following lines. But we can still get fully inferred access to a generic class, and all the benefits that entails, by traversing into them via generic function implicit typing (last line):
int t = 4;
typed_cache<int>.MyTypedCachedFunc(t); // no inference from 't', explicit type required
MyTypedCacheFunc<int>(t); // ok, (but redundant)
MyTypedCacheFunc(t); // ok, full inference
Designed well, inferred typing can effortlessly launch you into the appropriate automatically demand-cached data and behaviors, customized for each type (recall points 1. and 2). As noted, I find the approach useful, especially considering its simplicity.
The JITter ought to be inlining this as a simple bitwise operation. The JITter is aware enough to custom-handle even certain framework methods (via MethodImplOptions.InternalCall I think?) but HasFlag seems to have escaped Microsoft's serious attention.
I am wondering how I can fetch the incoming arguments of my method in an array. Or just retrieve the values of my arguments dynamically.
Meaning, a call like:
MyMethod(10, "eleven");
For method:
void MyMethod(int Test, str Test2) {}
Would resolve in an array like:
{{"Test" => 10}, {"Test2", "eleven"}}
Would be even better if I could achieve this with reflection.. Ex. somehow with StackTrace.
I think, what you are looking for does not exist. The closest you can have is params:
MyMethod(params object[] args)
{
// if you have to do this, it's quite bad:
int intArg = (int)args[0];
string stringArg = (string)arg[1]:
}
// call with any number (and type) of argument
MyMethod(7, "tr");
There is no compile time type checking, and therefore it is not an all-purpose way to handle arguments. But if your arguments are dynamic, it's probably a solution.
Edit: had another idea:
You need to put all argument manually into a list / dictionary. You can write a helper class to allow the following:
MyMethod(int arg1, string arg2)
{
Arguments.Add(() => arg1);
Arguments.Add(() => arg2);
//
}
The helper looks like this
public static void Add<T>(Expression<Func<T>> expr)
{
// run the expression to get the argument value
object value = expr.Compile()();
// get the argument name from the expression
string argumentName = ((MemberExpression)expr.Body).Member.Name;
// add it to some list:
argumentsDic.Add(argumentName, value);
}
Your best option is to do it with an anonymous type, as shown in this example.
Nice Question (+1). I think this is what you need -
MethodBase mb = MethodBase.GetCurrentMethod();
ParameterInfo[] pi = mb.GetParameters();
One way I know (not sure if it's the only way nowadays, but it used to be) is to use aspect-oriented programming (AOP), and in particular interception. It is a bit painful to roll it by hand, but there are excellent tools that come to the rescue. One such tool is PostSharp: http://www.postsharp.org/.
Since the method is using named parameters, why can't you just explicitly populate a dictionary with their names and values? There is little point in using reflection to get their names since you already know them.
As already stated, the params keyword can be used to define a method with a variable number of parameters, but by definition those are nameless.
I'm not sure what you are asking, in the way you've explained it, makes any sense. Perhaps you could elaborate further?
Maybe this won't be exactly what you were looking for, but I found I could get a reasonable compromise for my situation using a variation on the method Matt Hamilton suggested and making use of the implicit naming of anonymous type parameters:
public void MyMethod(string arg1, bool arg2, int arg3, int arg4)
{
var dictionary = new PropertyDictionary(new
{
arg1, arg2, arg3, arg4
});
}
public class PropertyDictionary : Dictionary<string, object>
{
public PropertyDictionary(object values)
{
if(values == null)
return;
foreach(PropertyDescriptor property in TypeDescriptor.GetProperties(values))
Add(property.Name, property.GetValue(values);
}
}
As I said, it may not be helpful in your situation, but in mine (unit testing a method which processes XML) it was very useful.
.Net 3.5 doesn't support tuples. Too bad, But not sure whether the future version of .net will support tuples or not?
I've just read this article from the MSDN Magazine: Building Tuple
Here are excerpts:
The upcoming 4.0 release of Microsoft
.NET Framework introduces a new type
called System.Tuple. System.Tuple is a
fixed-size collection of
heterogeneously typed data.
Like an array, a tuple has a fixed
size that can't be changed once it has
been created. Unlike an array, each
element in a tuple may be a different
type, and a tuple is able to guarantee
strong typing for each element.
There is already one example of a
tuple floating around the Microsoft
.NET Framework, in the
System.Collections.Generic namespace:
KeyValuePair. While KeyValuePair can be thought of as the same
as Tuple, since they are both
types that hold two things,
KeyValuePair feels different from
Tuple because it evokes a relationship
between the two values it stores (and
with good reason, as it supports the
Dictionary class).
Furthermore, tuples can be arbitrarily
sized, whereas KeyValuePair holds only
two things: a key and a value.
While some languages like F# have special syntax for tuples, you can use the new common tuple type from any language. Revisiting the first example, we can see that while useful, tuples can be overly verbose in languages without syntax for a tuple:
class Program {
static void Main(string[] args) {
Tuple<string, int> t = new Tuple<string, int>("Hello", 4);
PrintStringAndInt(t.Item1, t.Item2);
}
static void PrintStringAndInt(string s, int i) {
Console.WriteLine("{0} {1}", s, i);
}
}
Using the var keyword from C# 3.0, we can remove the type signature on the tuple variable, which allows for somewhat more readable code.
var t = new Tuple<string, int>("Hello", 4);
We've also added some factory methods to a static Tuple class which makes it easier to build tuples in a language that supports type inference, like C#.
var t = Tuple.Create("Hello", 4);
#region tuples
public class Tuple<T>
{
public Tuple(T first)
{
First = first;
}
public T First { get; set; }
}
public class Tuple<T, T2> : Tuple<T>
{
public Tuple(T first, T2 second)
: base(first)
{
Second = second;
}
public T2 Second { get; set; }
}
public class Tuple<T, T2, T3> : Tuple<T, T2>
{
public Tuple(T first, T2 second, T3 third)
: base(first, second)
{
Third = third;
}
public T3 Third { get; set; }
}
public class Tuple<T, T2, T3, T4> : Tuple<T, T2, T3>
{
public Tuple(T first, T2 second, T3 third, T4 fourth)
: base(first, second, third)
{
Fourth = fourth;
}
public T4 Fourth { get; set; }
}
#endregion
And to make declarations prettier:
public static class Tuple
{
//Allows Tuple.New(1, "2") instead of new Tuple<int, string>(1, "2")
public static Tuple<T1, T2> New<T1, T2>(T1 t1, T2 t2)
{
return new Tuple<T1, T2>(t1, t2);
}
//etc...
}
There is a proper (not quick) C# Tuple implementation in Lokad Shared Libraries (Open-source, of course) that includes following required features:
2-5 immutable tuple implementations
Proper DebuggerDisplayAttribute
Proper hashing and equality checks
Helpers for generating tuples from the provided parameters (generics are inferred by compiler) and extensions for collection-based operations.
production-tested.
Implementing Tuple classes or reusing F# classes within C# is only half the story - these give you the ability to create tuples with relative ease, but not really the syntactic sugar which makes them so nice to use in languages like F#.
For example in F# you can use pattern matching to extract both parts of a tuple within a let statment, eg
let (a, b) = someTupleFunc
Unfortunately to do the same using the F# classes from C# would be much less elegant:
Tuple<int,int> x = someTupleFunc();
int a = x.get_Item1();
int b = x.get_Item2();
Tuples represent a powerful method for returning multiple values from a function call without the need to litter your code with throwaway classes, or resorting to ugly ref or out parameters. However, in my opinion, without some syntactic sugar to make their creation and access more elegant, they are of limited use.
In my opinion, the anonymous types feature is not a tuple, but a very similar construct. The output of some LINQ Queries are collections of anonymous types, which behave like tuples.
Here is a statement, which creates a typed tuple :-) on the fly:
var p1 = new {a = "A", b = 3};
see: http://www.developer.com/net/csharp/article.php/3589916
C# 7 supports tuples natively:
var unnamedTuple = ("Peter", 29);
var namedTuple = (Name: "Peter", Age: 29);
(string Name, double Age) typedTuple = ("Peter", 29);
My open source .NET Sasa library has had tuples for years (along with plenty of other functionality, like full MIME parsing). I've been using it in production code for a good few years now.
C# supports simple tuples via generics quite easily (as per an earlier answer), and with "mumble typing" (one of many possible C# language enhancements) to improve type inference they could be very, very powerful.
For what it is worth, F# supports tuples natively, and having played with it, I'm not sure that (anonymous) tuples add much... what you gain in brevity you lose very quickly in code clarity.
For code within a single method, there are anonymous types; for code going outside of a method, I think I'll stick to simple named types. Of course, if a future C# makes it easier to make these immutable (while still easy to work with) I'll be happy.
Here's my set of tuples, they're autogenerated by a Python script, so I've perhaps gone a bit overboard:
Link to Subversion repository
You'll need a username/password, they're both guest
They are based on inheritance, but Tuple<Int32,String> will not compare equal to Tuple<Int32,String,Boolean> even if they happen to have the same values for the two first members.
They also implement GetHashCode and ToString and so forth, and lots of smallish helper methods.
Example of usage:
Tuple<Int32, String> t1 = new Tuple<Int32, String>(10, "a");
Tuple<Int32, String, Boolean> t2 = new Tuple<Int32, String, Boolean>(10, "a", true);
if (t1.Equals(t2))
Console.Out.WriteLine(t1 + " == " + t2);
else
Console.Out.WriteLine(t1 + " != " + t2);
Will output:
10, a != 10, a, True
If I remember my Computer Science classes correctly tuples are just data.
If you want grouped data - create classes that contain properties.
If you need something like the KeyValuePair then there it is.
I'd be surprised - C# is a strongly-typed language, whereas tuples are suited for more dynamically typed languages. C# has been drifting more dynamic as time goes on, but that's syntactic sugar, not a real shift in the underlying data types.
If you want two values in one instance, a KeyValuePair<> is a decent substitute, albeit clumsy. You can also make a struct or a class that'll do the same thing, and is expandable.
To make these useful in a hashtable or dictionary, you will likely want to provide overloads for GetHashCode and Equals.
If you go right now and type string.Format into your IDE, you'll see that there are 4 different overloads: one taking a string and object, another taking a string and two objects, then one taking three objects, and finally one that uses params. According to this answer, this is because params generates 'overhead', and some other languages may not support it.
My question is, why can't a method call like this:
void Foo()
{
Bar(1, 2, 3);
}
void Bar(params int[] args)
{
// use args...
}
Be essentially transformed at compile time to
void Foo()
{
Bar(new[] { 1, 2, 3 });
}
void Bar(int[] args)
{
// use args...
}
? Then it wouldn't create any overhead except for the array creation (which was necessary anyway), and would be fully compatible with other languages.
The number of arguments is already known at compile-time, so what's preventing the C# compiler from doing some kind of string substitution and making the first scenario essentially syntactic sugar for the second? Why did we have to implement hidden language features specifically to support variadic arguments?
The title makes an incorrect assumption.
Both a params and a non-params methods take an array; the difference is the compiler will emit the IL to create an array implicitly when making a params method call. An array is passed to both methods, as a single argument.
This can be seen in this .NET Fiddle (view "Tidy Up -> View IL").
using System;
public class Program
{
public static void Main()
{
var a1 = 1;
var a2 = 2;
var a3 = 3;
with_params(a1,a2,a3);
no_params(new [] {a1,a2,a3});
}
public static void with_params(params int[] x) {}
public static void no_params(int[] x) {}
}
In both cases the IL is identical; a new array is created, it is populated, and the array is supplied to the invoked method.
There is an "exception" to this identical IL generation in that the compiler can move out constant-valued arrays when used in the non-parameter form and use 'dup' initialization, as seen here. However, a new array is supplied as the argument in both cases.