What is the equivalent of a Tuple in .NET 3.5? [duplicate] - c#

Is there a class existing in .NET Framework 3.5 that would be equivalent to the .NET 4 Tuple?
I would like to use it in order to return several values from a method, rather than create a struct.

No, not in .Net 3.5. But it shouldn't be that hard to create your own.
public class Tuple<T1, T2>
{
public T1 First { get; private set; }
public T2 Second { get; private set; }
internal Tuple(T1 first, T2 second)
{
First = first;
Second = second;
}
}
public static class Tuple
{
public static Tuple<T1, T2> New<T1, T2>(T1 first, T2 second)
{
var tuple = new Tuple<T1, T2>(first, second);
return tuple;
}
}
UPDATE: Moved the static stuff to a static class to allow for type inference. With the update you can write stuff like var tuple = Tuple.New(5, "hello"); and it will fix the types for you implicitly.

I'm using this in my pre-4 projects:
public class Tuple<T1>
{
public Tuple(T1 item1)
{
Item1 = item1;
}
public T1 Item1 { get; set; }
}
public class Tuple<T1, T2> : Tuple<T1>
{
public Tuple(T1 item1, T2 item2) : base(item1)
{
Item2 = item2;
}
public T2 Item2 { get; set; }
}
public class Tuple<T1, T2, T3> : Tuple<T1, T2>
{
public Tuple(T1 item1, T2 item2, T3 item3) : base(item1, item2)
{
Item3 = item3;
}
public T3 Item3 { get; set; }
}
public static class Tuple
{
public static Tuple<T1> Create<T1>(T1 item1)
{
return new Tuple<T1>(item1);
}
public static Tuple<T1, T2> Create<T1, T2>(T1 item1, T2 item2)
{
return new Tuple<T1, T2>(item1, item2);
}
public static Tuple<T1, T2, T3> Create<T1, T2, T3>(T1 item1, T2 item2, T3 item3)
{
return new Tuple<T1, T2, T3>(item1, item2, item3);
}
}

In the event that you need them to have feature-parity with .Net 4.0 (primarily comparisson):
static class Tuple
{
public static Tuple<T1, T2> Create<T1, T2>(T1 item1, T2 item2)
{
return new Tuple<T1, T2>(item1, item2);
}
}
[DebuggerDisplay("Item1={Item1};Item2={Item2}")]
class Tuple<T1, T2> : IFormattable
{
public T1 Item1 { get; private set; }
public T2 Item2 { get; private set; }
public Tuple(T1 item1, T2 item2)
{
Item1 = item1;
Item2 = item2;
}
#region Optional - If you need to use in dictionaries or check equality
private static readonly IEqualityComparer<T1> Item1Comparer = EqualityComparer<T1>.Default;
private static readonly IEqualityComparer<T2> Item2Comparer = EqualityComparer<T2>.Default;
public override int GetHashCode()
{
var hc = 0;
if (!object.ReferenceEquals(Item1, null))
hc = Item1Comparer.GetHashCode(Item1);
if (!object.ReferenceEquals(Item2, null))
hc = (hc << 3) ^ Item2Comparer.GetHashCode(Item2);
return hc;
}
public override bool Equals(object obj)
{
var other = obj as Tuple<T1, T2>;
if (object.ReferenceEquals(other, null))
return false;
else
return Item1Comparer.Equals(Item1, other.Item1) && Item2Comparer.Equals(Item2, other.Item2);
}
#endregion
#region Optional - If you need to do string-based formatting
public override string ToString() { return ToString(null, CultureInfo.CurrentCulture); }
public string ToString(string format, IFormatProvider formatProvider)
{
return string.Format(formatProvider, format ?? "{0},{1}", Item1, Item2);
}
#endregion
}

You can install NetLegacySupport.Tuple via nuget. This is the Tuple class from .Net 4.5 backported to .Net 2.0 and 3.5.
You can install this via the package manager in Visual Studio or using nuget on the commandline.
Here is the nuget package:
https://www.nuget.org/packages/NetLegacySupport.Tuple

Yes, there is a class called System.Collections.Generic.KeyValuePair that does the same thing (since .NET 2.0 I think).
http://msdn.microsoft.com/en-us/library/5tbh8a42.aspx

Yes, you can just use Tuple.cs from mono:
You require the dependencies as well:
Tuples.cs
IStructuralComparable.cs
IStructuralEquatable.cs
You just put a
#define NET_4_0
in front of every
#if NET_4_0
and there you go, a feature-complete implementation of System.Tuple for .NET 2.0.

Related

How to set item name in c# tuple? [duplicate]

Is there a way to use a Tuple class, but supply the names of the items in it?
For example:
public Tuple<int, int, int int> GetOrderRelatedIds()
That returns the ids for OrderGroupId, OrderTypeId, OrderSubTypeId and OrderRequirementId.
It would be nice to let the users of my method know which is which. (When you call the method, the results are result.Item1, result.Item2, result.Item3, result.Item4. It is not clear which one is which.)
(I know I could just create a class to hold all these Ids, but it these Ids already have their own classes they live in and making a class for this one method's return value seems silly.)
In C# 7.0 (Visual Studio 2017) there is a new construction to do that:
(string first, string middle, string last) LookupName(long id)
Up to C# 7.0, there was no way to do this short of defining your own type.
Here is an overly complicated version of what you are asking:
class MyTuple : Tuple<int, int>
{
public MyTuple(int one, int two)
:base(one, two)
{
}
public int OrderGroupId { get{ return this.Item1; } }
public int OrderTypeId { get{ return this.Item2; } }
}
Why not just make a class?
Reproducing my answer from this post as it is a better fit here.
Starting C# v7.0, it is now possible to name the tuple properties which earlier used to default to names like Item1, Item2 and so on.
Naming the properties of Tuple Literals:
var myDetails = (MyName: "Foo", MyAge: 22, MyFavoriteFood: "Bar");
Console.WriteLine($"Name - {myDetails.MyName}, Age - {myDetails.MyAge}, Passion - {myDetails.MyFavoriteFood}");
The output on console:
Name - Foo, Age - 22, Passion - Bar
Returning Tuple (having named properties) from a method:
static void Main(string[] args)
{
var empInfo = GetEmpInfo();
Console.WriteLine($"Employee Details: {empInfo.firstName}, {empInfo.lastName}, {empInfo.computerName}, {empInfo.Salary}");
}
static (string firstName, string lastName, string computerName, int Salary) GetEmpInfo()
{
//This is hardcoded just for the demonstration. Ideally this data might be coming from some DB or web service call
return ("Foo", "Bar", "Foo-PC", 1000);
}
The output on console:
Employee Details: Foo, Bar, Foo-PC, 1000
Creating a list of Tuples having named properties
var tupleList = new List<(int Index, string Name)>
{
(1, "cow"),
(5, "chickens"),
(1, "airplane")
};
foreach (var tuple in tupleList)
Console.WriteLine($"{tuple.Index} - {tuple.Name}");
Output on console:
1 - cow
5 - chickens
1 - airplane
Note: Code snippets in this post are using string interpolation feature of C# v6 as detailed here.
TL:DR -> System.ValueTuples can have custom names for fields, System.Tuples cannot.
Just to clarify, there are 2 different types of tuples in C# 7.0 and later.
System.Tuple
and
System.ValueTuple
When you declare a tuple via the Tuple<...> class:
public Tuple<int, string, int> GetUserInfo();
You're declaring a Tuple object data type.
When you declare a tuple via parenthesis:
public (int id, string name, int age) GetUserInfo();
You're declaring a ValueTuple value data type.
Each one functions and behaves differently. In your question, your method returns a System.Tuple object.
Unfortunately, Tuple objects created via the System.Tuple class have no built in functionality to give each property a custom name. They always default to ItemN depending on how many properties they contain.
System.ValueTuple values on the other hand can contain custom named fields.
For more info, you can refer to Tuple types (C# reference) and/or the links to each class above. But essentially some of the key differences of the 2 different types of tuples that the documentation highlights are:
C# tuples, which are backed by System.ValueTuple types, are different
from tuples that are represented by System.Tuple types. The main
differences are as follows:
System.ValueTuple types are value types. System.Tuple types are reference types.
System.ValueTuple types are mutable. System.Tuple types are immutable.
Data members of System.ValueTuple types are fields. Data members of System.Tuple types are properties.
So if your method needs to return a System.Tuple object or you desire the behavior of that type of object more, then as of writing this, you can't achieve what you want. However, if your method can return a System.ValueTuple value, then you can give it custom named fields in the returned value.
With .net 4 you could perhaps look at the ExpandoObject, however, don't use it for this simple case as what would have been compile-time errors become run-time errors.
class Program
{
static void Main(string[] args)
{
dynamic employee, manager;
employee = new ExpandoObject();
employee.Name = "John Smith";
employee.Age = 33;
manager = new ExpandoObject();
manager.Name = "Allison Brown";
manager.Age = 42;
manager.TeamSize = 10;
WritePerson(manager);
WritePerson(employee);
}
private static void WritePerson(dynamic person)
{
Console.WriteLine("{0} is {1} years old.",
person.Name, person.Age);
// The following statement causes an exception
// if you pass the employee object.
// Console.WriteLine("Manages {0} people", person.TeamSize);
}
}
// This code example produces the following output:
// John Smith is 33 years old.
// Allison Brown is 42 years old.
Something else worth mentioning is an anonymous type for within a method, but you need to create a class if you want to return it.
var MyStuff = new
{
PropertyName1 = 10,
PropertyName2 = "string data",
PropertyName3 = new ComplexType()
};
MichaelMocko Answered is great,
but I want to add a few things which I had to figure out
(string first, string middle, string last) LookupName(long id)
above Line will give you compile-time error if you are using .net framework < 4.7
So if you have a project that is using .net framework < 4.7 and still you want to use ValueTuple than workAround would be installing this NuGet package
Update:
Example of returning Named tuple from a method and using it
public static (string extension, string fileName) GetFile()
{
return ("png", "test");
}
Using it
var (extension, fileName) = GetFile();
Console.WriteLine(extension);
Console.WriteLine(fileName);
As of today, it's this simple. Instead of using the Tuple keyword
public Tuple<int, int, int int> GetOrderRelatedIds()
Use this.
public (int alpha, int beta, int candor) GetOrderRelatedIds()
Get the values like this.
var a = GetOrderRelatedIds();
var c = a.alpha;
Just to add to #MichaelMocko answer. Tuples have couple of gotchas at the moment:
You can't use them in EF expression trees
Example:
public static (string name, string surname) GetPersonName(this PersonContext ctx, int id)
{
return ctx.Persons
.Where(person => person.Id == id)
// Selecting as Tuple
.Select(person => (person.Name, person.Surname))
.First();
}
This will fail to compile with "An expression tree may not contain a tuple literal" error. Unfortunately, the expression trees API wasn't expanded with support for tuples when these were added to the language.
Track (and upvote) this issue for the updates: https://github.com/dotnet/roslyn/issues/12897
To get around the problem, you can cast it to anonymous type first and then convert the value to tuple:
// Will work
public static (string name, string surname) GetPersonName(this PersonContext ctx, int id)
{
return ctx.Persons
.Where(person => person.Id == id)
.Select(person => new { person.Name, person.Surname })
.ToList()
.Select(person => (person.Name, person.Surname))
.First();
}
Another option is to use ValueTuple.Create:
// Will work
public static (string name, string surname) GetPersonName(this PersonContext ctx, int id)
{
return ctx.Persons
.Where(person => person.Id == id)
.Select(person => ValueTuple.Create(person.Name, person.Surname))
.First();
}
References:
https://www.damirscorner.com/blog/posts/20181207-NoSupportForTuplesInExpressionTrees.html
Convert anonymous type to new C# 7 tuple type
You can't deconstruct them in lambdas
There's a proposal to add the support: https://github.com/dotnet/csharplang/issues/258
Example:
public static IQueryable<(string name, string surname)> GetPersonName(this PersonContext ctx, int id)
{
return ctx.Persons
.Where(person => person.Id == id)
.Select(person => ValueTuple.Create(person.Name, person.Surname));
}
// This won't work
ctx.GetPersonName(id).Select((name, surname) => { return name + surname; })
// But this will
ctx.GetPersonName(id).Select(t => { return t.name + t.surname; })
References:
C# 7 tuples and lambdas
They won't serialize nicely
using System;
using Newtonsoft.Json;
public class Program
{
public static void Main() {
var me = (age: 21, favoriteFood: "Custard");
string json = JsonConvert.SerializeObject(me);
// Will output {"Item1":21,"Item2":"Custard"}
Console.WriteLine(json);
}
}
Tuple field names are only available at compile time and are completely wiped out at runtime.
References:
Make Value Tuple property names resolvable at runtime (CSharpLang)
C#7 Tuple Support (Newtonsoft.Json)
No, you can't name the tuple members.
The in-between would be to use ExpandoObject instead of Tuple.
If the types of your items are all different, here is a class I made to get them more intuitively.
The usage of this class:
var t = TypedTuple.Create("hello", 1, new MyClass());
var s = t.Get<string>();
var i = t.Get<int>();
var c = t.Get<MyClass>();
Source code:
public static class TypedTuple
{
public static TypedTuple<T1> Create<T1>(T1 t1)
{
return new TypedTuple<T1>(t1);
}
public static TypedTuple<T1, T2> Create<T1, T2>(T1 t1, T2 t2)
{
return new TypedTuple<T1, T2>(t1, t2);
}
public static TypedTuple<T1, T2, T3> Create<T1, T2, T3>(T1 t1, T2 t2, T3 t3)
{
return new TypedTuple<T1, T2, T3>(t1, t2, t3);
}
public static TypedTuple<T1, T2, T3, T4> Create<T1, T2, T3, T4>(T1 t1, T2 t2, T3 t3, T4 t4)
{
return new TypedTuple<T1, T2, T3, T4>(t1, t2, t3, t4);
}
public static TypedTuple<T1, T2, T3, T4, T5> Create<T1, T2, T3, T4, T5>(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5)
{
return new TypedTuple<T1, T2, T3, T4, T5>(t1, t2, t3, t4, t5);
}
public static TypedTuple<T1, T2, T3, T4, T5, T6> Create<T1, T2, T3, T4, T5, T6>(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6)
{
return new TypedTuple<T1, T2, T3, T4, T5, T6>(t1, t2, t3, t4, t5, t6);
}
public static TypedTuple<T1, T2, T3, T4, T5, T6, T7> Create<T1, T2, T3, T4, T5, T6, T7>(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7)
{
return new TypedTuple<T1, T2, T3, T4, T5, T6, T7>(t1, t2, t3, t4, t5, t6, t7);
}
public static TypedTuple<T1, T2, T3, T4, T5, T6, T7, T8> Create<T1, T2, T3, T4, T5, T6, T7, T8>(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8)
{
return new TypedTuple<T1, T2, T3, T4, T5, T6, T7, T8>(t1, t2, t3, t4, t5, t6, t7, t8);
}
}
public class TypedTuple<T>
{
protected Dictionary<Type, object> items = new Dictionary<Type, object>();
public TypedTuple(T item1)
{
Item1 = item1;
}
public TSource Get<TSource>()
{
object value;
if (this.items.TryGetValue(typeof(TSource), out value))
{
return (TSource)value;
}
else
return default(TSource);
}
private T item1;
public T Item1 { get { return this.item1; } set { this.item1 = value; this.items[typeof(T)] = value; } }
}
public class TypedTuple<T1, T2> : TypedTuple<T1>
{
public TypedTuple(T1 item1, T2 item2)
: base(item1)
{
Item2 = item2;
}
private T2 item2;
public T2 Item2 { get { return this.item2; } set { this.item2 = value; this.items[typeof(T2)] = value; } }
}
public class TypedTuple<T1, T2, T3> : TypedTuple<T1, T2>
{
public TypedTuple(T1 item1, T2 item2, T3 item3)
: base(item1, item2)
{
Item3 = item3;
}
private T3 item3;
public T3 Item3 { get { return this.item3; } set { this.item3 = value; this.items[typeof(T3)] = value; } }
}
public class TypedTuple<T1, T2, T3, T4> : TypedTuple<T1, T2, T3>
{
public TypedTuple(T1 item1, T2 item2, T3 item3, T4 item4)
: base(item1, item2, item3)
{
Item4 = item4;
}
private T4 item4;
public T4 Item4 { get { return this.item4; } set { this.item4 = value; this.items[typeof(T4)] = value; } }
}
public class TypedTuple<T1, T2, T3, T4, T5> : TypedTuple<T1, T2, T3, T4>
{
public TypedTuple(T1 item1, T2 item2, T3 item3, T4 item4, T5 item5)
: base(item1, item2, item3, item4)
{
Item5 = item5;
}
private T5 item5;
public T5 Item5 { get { return this.item5; } set { this.item5 = value; this.items[typeof(T5)] = value; } }
}
public class TypedTuple<T1, T2, T3, T4, T5, T6> : TypedTuple<T1, T2, T3, T4, T5>
{
public TypedTuple(T1 item1, T2 item2, T3 item3, T4 item4, T5 item5, T6 item6)
: base(item1, item2, item3, item4, item5)
{
Item6 = item6;
}
private T6 item6;
public T6 Item6 { get { return this.item6; } set { this.item6 = value; this.items[typeof(T6)] = value; } }
}
public class TypedTuple<T1, T2, T3, T4, T5, T6, T7> : TypedTuple<T1, T2, T3, T4, T5, T6>
{
public TypedTuple(T1 item1, T2 item2, T3 item3, T4 item4, T5 item5, T6 item6, T7 item7)
: base(item1, item2, item3, item4, item5, item6)
{
Item7 = item7;
}
private T7 item7;
public T7 Item7 { get { return this.item7; } set { this.item7 = value; this.items[typeof(T7)] = value; } }
}
public class TypedTuple<T1, T2, T3, T4, T5, T6, T7, T8> : TypedTuple<T1, T2, T3, T4, T5, T6, T7>
{
public TypedTuple(T1 item1, T2 item2, T3 item3, T4 item4, T5 item5, T6 item6, T7 item7, T8 item8)
: base(item1, item2, item3, item4, item5, item6, item7)
{
Item8 = item8;
}
private T8 item8;
public T8 Item8 { get { return this.item8; } set { this.item8 = value; this.items[typeof(T8)] = value; } }
}
This is very annoying and I expect future versions of C# will address this need. I find the easiest work around to be either use a different data structure type or rename the "items" for your sanity and for the sanity of others reading your code.
Tuple<ApiResource, JSendResponseStatus> result = await SendApiRequest();
ApiResource apiResource = result.Item1;
JSendResponseStatus jSendStatus = result.Item2;
(double, int) t1 = (4.5, 3);
Console.WriteLine($"Tuple with elements {t1.Item1} and {t1.Item2}.");
// Output:
// Tuple with elements 4.5 and 3.
(double Sum, int Count) t2 = (4.5, 3);
Console.WriteLine($"Sum of {t2.Count} elements is {t2.Sum}.");
// Output:
// Sum of 3 elements is 4.5.
From Docs: https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/value-tuples
Why not using a multiple returns instead of using tuple
var handler = GenerateFromMethod1(hits);
Process(handler.string1, handler.string1);
private static (string string1, string string2) GenerateFromMethod1()
{
}
I think I would create a class but another alternative is output parameters.
public void GetOrderRelatedIds(out int OrderGroupId, out int OrderTypeId, out int OrderSubTypeId, out int OrderRequirementId)
Since your Tuple only contains integers you could represent it with a Dictionary<string,int>
var orderIds = new Dictionary<string, int> {
{"OrderGroupId", 1},
{"OrderTypeId", 2},
{"OrderSubTypeId", 3},
{"OrderRequirementId", 4}.
};
but I don't recommend that either.
Why is everyone making life so hard. Tuples are for rather temporary data processing. Working with Tuples all the time will make the code very hard to understand at some point. Creating classes for everything could eventually bloat your project.
It's about balance, however...
Your problem seems to be something you would want a class for. And just for the sake of completeness, this class below also contains constructors.
This is the proper pattern for
A custom data type
with no further functionality. Getters and setters can also be expanded with code, getting/setting private members with the name pattern of "_orderGroupId", while also executing functional code.
Including constructors. You can also choose to include just one constructor if all properties are mandatory.
If you want to use all constructors, bubbling like this is the proper pattern to avoid duplicate code.
public class OrderRelatedIds
{
public int OrderGroupId { get; set; }
public int OrderTypeId { get; set; }
public int OrderSubTypeId { get; set; }
public int OrderRequirementId { get; set; }
public OrderRelatedIds()
{
}
public OrderRelatedIds(int orderGroupId)
: this()
{
OrderGroupId = orderGroupId;
}
public OrderRelatedIds(int orderGroupId, int orderTypeId)
: this(orderGroupId)
{
OrderTypeId = orderTypeId;
}
public OrderRelatedIds(int orderGroupId, int orderTypeId, int orderSubTypeId)
: this(orderGroupId, orderTypeId)
{
OrderSubTypeId = orderSubTypeId;
}
public OrderRelatedIds(int orderGroupId, int orderTypeId, int orderSubTypeId, int orderRequirementId)
: this(orderGroupId, orderTypeId, orderSubTypeId)
{
OrderRequirementId = orderRequirementId;
}
}
Or, if you want it really simple: You can also use type initializers:
OrderRelatedIds orders = new OrderRelatedIds
{
OrderGroupId = 1,
OrderTypeId = 2,
OrderSubTypeId = 3,
OrderRequirementId = 4
};
public class OrderRelatedIds
{
public int OrderGroupId;
public int OrderTypeId;
public int OrderSubTypeId;
public int OrderRequirementId;
}
I would write the Item names in the summay..
so by hovering over the function helloworld() the text will say hello = Item1 and world = Item2
helloworld("Hi1,Hi2");
/// <summary>
/// Return hello = Item1 and world Item2
/// </summary>
/// <param name="input">string to split</param>
/// <returns></returns>
private static Tuple<bool, bool> helloworld(string input)
{
bool hello = false;
bool world = false;
foreach (var hw in input.Split(','))
{
switch (hw)
{
case "Hi1":
hello= true;
break;
case "Hi2":
world= true;
break;
}
}
return new Tuple<bool, bool>(hello, world);
}
You Can write a class that contains the Tuple.
You need to override the Equals and GetHashCode functions
and the == and != operators.
class Program
{
public class MyTuple
{
private Tuple<int, int> t;
public MyTuple(int a, int b)
{
t = new Tuple<int, int>(a, b);
}
public int A
{
get
{
return t.Item1;
}
}
public int B
{
get
{
return t.Item2;
}
}
public override bool Equals(object obj)
{
return t.Equals(((MyTuple)obj).t);
}
public override int GetHashCode()
{
return t.GetHashCode();
}
public static bool operator ==(MyTuple m1, MyTuple m2)
{
return m1.Equals(m2);
}
public static bool operator !=(MyTuple m1, MyTuple m2)
{
return !m1.Equals(m2);
}
}
static void Main(string[] args)
{
var v1 = new MyTuple(1, 2);
var v2 = new MyTuple(1, 2);
Console.WriteLine(v1 == v2);
Dictionary<MyTuple, int> d = new Dictionary<MyTuple, int>();
d.Add(v1, 1);
Console.WriteLine(d.ContainsKey(v2));
}
}
will return:
True
True
C# 7 tuple example
var tuple = TupleExample(key, value);
private (string key1, long value1) ValidateAPIKeyOwnerId(string key, string value)
{
return (key, value);
}
if (!string.IsNullOrEmpty(tuple.key1) && tuple.value1 > 0)
{
//your code
}

How can you name a tuple used as a function parameter in C#? [duplicate]

Is there a way to use a Tuple class, but supply the names of the items in it?
For example:
public Tuple<int, int, int int> GetOrderRelatedIds()
That returns the ids for OrderGroupId, OrderTypeId, OrderSubTypeId and OrderRequirementId.
It would be nice to let the users of my method know which is which. (When you call the method, the results are result.Item1, result.Item2, result.Item3, result.Item4. It is not clear which one is which.)
(I know I could just create a class to hold all these Ids, but it these Ids already have their own classes they live in and making a class for this one method's return value seems silly.)
In C# 7.0 (Visual Studio 2017) there is a new construction to do that:
(string first, string middle, string last) LookupName(long id)
Up to C# 7.0, there was no way to do this short of defining your own type.
Here is an overly complicated version of what you are asking:
class MyTuple : Tuple<int, int>
{
public MyTuple(int one, int two)
:base(one, two)
{
}
public int OrderGroupId { get{ return this.Item1; } }
public int OrderTypeId { get{ return this.Item2; } }
}
Why not just make a class?
Reproducing my answer from this post as it is a better fit here.
Starting C# v7.0, it is now possible to name the tuple properties which earlier used to default to names like Item1, Item2 and so on.
Naming the properties of Tuple Literals:
var myDetails = (MyName: "Foo", MyAge: 22, MyFavoriteFood: "Bar");
Console.WriteLine($"Name - {myDetails.MyName}, Age - {myDetails.MyAge}, Passion - {myDetails.MyFavoriteFood}");
The output on console:
Name - Foo, Age - 22, Passion - Bar
Returning Tuple (having named properties) from a method:
static void Main(string[] args)
{
var empInfo = GetEmpInfo();
Console.WriteLine($"Employee Details: {empInfo.firstName}, {empInfo.lastName}, {empInfo.computerName}, {empInfo.Salary}");
}
static (string firstName, string lastName, string computerName, int Salary) GetEmpInfo()
{
//This is hardcoded just for the demonstration. Ideally this data might be coming from some DB or web service call
return ("Foo", "Bar", "Foo-PC", 1000);
}
The output on console:
Employee Details: Foo, Bar, Foo-PC, 1000
Creating a list of Tuples having named properties
var tupleList = new List<(int Index, string Name)>
{
(1, "cow"),
(5, "chickens"),
(1, "airplane")
};
foreach (var tuple in tupleList)
Console.WriteLine($"{tuple.Index} - {tuple.Name}");
Output on console:
1 - cow
5 - chickens
1 - airplane
Note: Code snippets in this post are using string interpolation feature of C# v6 as detailed here.
TL:DR -> System.ValueTuples can have custom names for fields, System.Tuples cannot.
Just to clarify, there are 2 different types of tuples in C# 7.0 and later.
System.Tuple
and
System.ValueTuple
When you declare a tuple via the Tuple<...> class:
public Tuple<int, string, int> GetUserInfo();
You're declaring a Tuple object data type.
When you declare a tuple via parenthesis:
public (int id, string name, int age) GetUserInfo();
You're declaring a ValueTuple value data type.
Each one functions and behaves differently. In your question, your method returns a System.Tuple object.
Unfortunately, Tuple objects created via the System.Tuple class have no built in functionality to give each property a custom name. They always default to ItemN depending on how many properties they contain.
System.ValueTuple values on the other hand can contain custom named fields.
For more info, you can refer to Tuple types (C# reference) and/or the links to each class above. But essentially some of the key differences of the 2 different types of tuples that the documentation highlights are:
C# tuples, which are backed by System.ValueTuple types, are different
from tuples that are represented by System.Tuple types. The main
differences are as follows:
System.ValueTuple types are value types. System.Tuple types are reference types.
System.ValueTuple types are mutable. System.Tuple types are immutable.
Data members of System.ValueTuple types are fields. Data members of System.Tuple types are properties.
So if your method needs to return a System.Tuple object or you desire the behavior of that type of object more, then as of writing this, you can't achieve what you want. However, if your method can return a System.ValueTuple value, then you can give it custom named fields in the returned value.
With .net 4 you could perhaps look at the ExpandoObject, however, don't use it for this simple case as what would have been compile-time errors become run-time errors.
class Program
{
static void Main(string[] args)
{
dynamic employee, manager;
employee = new ExpandoObject();
employee.Name = "John Smith";
employee.Age = 33;
manager = new ExpandoObject();
manager.Name = "Allison Brown";
manager.Age = 42;
manager.TeamSize = 10;
WritePerson(manager);
WritePerson(employee);
}
private static void WritePerson(dynamic person)
{
Console.WriteLine("{0} is {1} years old.",
person.Name, person.Age);
// The following statement causes an exception
// if you pass the employee object.
// Console.WriteLine("Manages {0} people", person.TeamSize);
}
}
// This code example produces the following output:
// John Smith is 33 years old.
// Allison Brown is 42 years old.
Something else worth mentioning is an anonymous type for within a method, but you need to create a class if you want to return it.
var MyStuff = new
{
PropertyName1 = 10,
PropertyName2 = "string data",
PropertyName3 = new ComplexType()
};
MichaelMocko Answered is great,
but I want to add a few things which I had to figure out
(string first, string middle, string last) LookupName(long id)
above Line will give you compile-time error if you are using .net framework < 4.7
So if you have a project that is using .net framework < 4.7 and still you want to use ValueTuple than workAround would be installing this NuGet package
Update:
Example of returning Named tuple from a method and using it
public static (string extension, string fileName) GetFile()
{
return ("png", "test");
}
Using it
var (extension, fileName) = GetFile();
Console.WriteLine(extension);
Console.WriteLine(fileName);
As of today, it's this simple. Instead of using the Tuple keyword
public Tuple<int, int, int int> GetOrderRelatedIds()
Use this.
public (int alpha, int beta, int candor) GetOrderRelatedIds()
Get the values like this.
var a = GetOrderRelatedIds();
var c = a.alpha;
Just to add to #MichaelMocko answer. Tuples have couple of gotchas at the moment:
You can't use them in EF expression trees
Example:
public static (string name, string surname) GetPersonName(this PersonContext ctx, int id)
{
return ctx.Persons
.Where(person => person.Id == id)
// Selecting as Tuple
.Select(person => (person.Name, person.Surname))
.First();
}
This will fail to compile with "An expression tree may not contain a tuple literal" error. Unfortunately, the expression trees API wasn't expanded with support for tuples when these were added to the language.
Track (and upvote) this issue for the updates: https://github.com/dotnet/roslyn/issues/12897
To get around the problem, you can cast it to anonymous type first and then convert the value to tuple:
// Will work
public static (string name, string surname) GetPersonName(this PersonContext ctx, int id)
{
return ctx.Persons
.Where(person => person.Id == id)
.Select(person => new { person.Name, person.Surname })
.ToList()
.Select(person => (person.Name, person.Surname))
.First();
}
Another option is to use ValueTuple.Create:
// Will work
public static (string name, string surname) GetPersonName(this PersonContext ctx, int id)
{
return ctx.Persons
.Where(person => person.Id == id)
.Select(person => ValueTuple.Create(person.Name, person.Surname))
.First();
}
References:
https://www.damirscorner.com/blog/posts/20181207-NoSupportForTuplesInExpressionTrees.html
Convert anonymous type to new C# 7 tuple type
You can't deconstruct them in lambdas
There's a proposal to add the support: https://github.com/dotnet/csharplang/issues/258
Example:
public static IQueryable<(string name, string surname)> GetPersonName(this PersonContext ctx, int id)
{
return ctx.Persons
.Where(person => person.Id == id)
.Select(person => ValueTuple.Create(person.Name, person.Surname));
}
// This won't work
ctx.GetPersonName(id).Select((name, surname) => { return name + surname; })
// But this will
ctx.GetPersonName(id).Select(t => { return t.name + t.surname; })
References:
C# 7 tuples and lambdas
They won't serialize nicely
using System;
using Newtonsoft.Json;
public class Program
{
public static void Main() {
var me = (age: 21, favoriteFood: "Custard");
string json = JsonConvert.SerializeObject(me);
// Will output {"Item1":21,"Item2":"Custard"}
Console.WriteLine(json);
}
}
Tuple field names are only available at compile time and are completely wiped out at runtime.
References:
Make Value Tuple property names resolvable at runtime (CSharpLang)
C#7 Tuple Support (Newtonsoft.Json)
No, you can't name the tuple members.
The in-between would be to use ExpandoObject instead of Tuple.
If the types of your items are all different, here is a class I made to get them more intuitively.
The usage of this class:
var t = TypedTuple.Create("hello", 1, new MyClass());
var s = t.Get<string>();
var i = t.Get<int>();
var c = t.Get<MyClass>();
Source code:
public static class TypedTuple
{
public static TypedTuple<T1> Create<T1>(T1 t1)
{
return new TypedTuple<T1>(t1);
}
public static TypedTuple<T1, T2> Create<T1, T2>(T1 t1, T2 t2)
{
return new TypedTuple<T1, T2>(t1, t2);
}
public static TypedTuple<T1, T2, T3> Create<T1, T2, T3>(T1 t1, T2 t2, T3 t3)
{
return new TypedTuple<T1, T2, T3>(t1, t2, t3);
}
public static TypedTuple<T1, T2, T3, T4> Create<T1, T2, T3, T4>(T1 t1, T2 t2, T3 t3, T4 t4)
{
return new TypedTuple<T1, T2, T3, T4>(t1, t2, t3, t4);
}
public static TypedTuple<T1, T2, T3, T4, T5> Create<T1, T2, T3, T4, T5>(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5)
{
return new TypedTuple<T1, T2, T3, T4, T5>(t1, t2, t3, t4, t5);
}
public static TypedTuple<T1, T2, T3, T4, T5, T6> Create<T1, T2, T3, T4, T5, T6>(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6)
{
return new TypedTuple<T1, T2, T3, T4, T5, T6>(t1, t2, t3, t4, t5, t6);
}
public static TypedTuple<T1, T2, T3, T4, T5, T6, T7> Create<T1, T2, T3, T4, T5, T6, T7>(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7)
{
return new TypedTuple<T1, T2, T3, T4, T5, T6, T7>(t1, t2, t3, t4, t5, t6, t7);
}
public static TypedTuple<T1, T2, T3, T4, T5, T6, T7, T8> Create<T1, T2, T3, T4, T5, T6, T7, T8>(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8)
{
return new TypedTuple<T1, T2, T3, T4, T5, T6, T7, T8>(t1, t2, t3, t4, t5, t6, t7, t8);
}
}
public class TypedTuple<T>
{
protected Dictionary<Type, object> items = new Dictionary<Type, object>();
public TypedTuple(T item1)
{
Item1 = item1;
}
public TSource Get<TSource>()
{
object value;
if (this.items.TryGetValue(typeof(TSource), out value))
{
return (TSource)value;
}
else
return default(TSource);
}
private T item1;
public T Item1 { get { return this.item1; } set { this.item1 = value; this.items[typeof(T)] = value; } }
}
public class TypedTuple<T1, T2> : TypedTuple<T1>
{
public TypedTuple(T1 item1, T2 item2)
: base(item1)
{
Item2 = item2;
}
private T2 item2;
public T2 Item2 { get { return this.item2; } set { this.item2 = value; this.items[typeof(T2)] = value; } }
}
public class TypedTuple<T1, T2, T3> : TypedTuple<T1, T2>
{
public TypedTuple(T1 item1, T2 item2, T3 item3)
: base(item1, item2)
{
Item3 = item3;
}
private T3 item3;
public T3 Item3 { get { return this.item3; } set { this.item3 = value; this.items[typeof(T3)] = value; } }
}
public class TypedTuple<T1, T2, T3, T4> : TypedTuple<T1, T2, T3>
{
public TypedTuple(T1 item1, T2 item2, T3 item3, T4 item4)
: base(item1, item2, item3)
{
Item4 = item4;
}
private T4 item4;
public T4 Item4 { get { return this.item4; } set { this.item4 = value; this.items[typeof(T4)] = value; } }
}
public class TypedTuple<T1, T2, T3, T4, T5> : TypedTuple<T1, T2, T3, T4>
{
public TypedTuple(T1 item1, T2 item2, T3 item3, T4 item4, T5 item5)
: base(item1, item2, item3, item4)
{
Item5 = item5;
}
private T5 item5;
public T5 Item5 { get { return this.item5; } set { this.item5 = value; this.items[typeof(T5)] = value; } }
}
public class TypedTuple<T1, T2, T3, T4, T5, T6> : TypedTuple<T1, T2, T3, T4, T5>
{
public TypedTuple(T1 item1, T2 item2, T3 item3, T4 item4, T5 item5, T6 item6)
: base(item1, item2, item3, item4, item5)
{
Item6 = item6;
}
private T6 item6;
public T6 Item6 { get { return this.item6; } set { this.item6 = value; this.items[typeof(T6)] = value; } }
}
public class TypedTuple<T1, T2, T3, T4, T5, T6, T7> : TypedTuple<T1, T2, T3, T4, T5, T6>
{
public TypedTuple(T1 item1, T2 item2, T3 item3, T4 item4, T5 item5, T6 item6, T7 item7)
: base(item1, item2, item3, item4, item5, item6)
{
Item7 = item7;
}
private T7 item7;
public T7 Item7 { get { return this.item7; } set { this.item7 = value; this.items[typeof(T7)] = value; } }
}
public class TypedTuple<T1, T2, T3, T4, T5, T6, T7, T8> : TypedTuple<T1, T2, T3, T4, T5, T6, T7>
{
public TypedTuple(T1 item1, T2 item2, T3 item3, T4 item4, T5 item5, T6 item6, T7 item7, T8 item8)
: base(item1, item2, item3, item4, item5, item6, item7)
{
Item8 = item8;
}
private T8 item8;
public T8 Item8 { get { return this.item8; } set { this.item8 = value; this.items[typeof(T8)] = value; } }
}
This is very annoying and I expect future versions of C# will address this need. I find the easiest work around to be either use a different data structure type or rename the "items" for your sanity and for the sanity of others reading your code.
Tuple<ApiResource, JSendResponseStatus> result = await SendApiRequest();
ApiResource apiResource = result.Item1;
JSendResponseStatus jSendStatus = result.Item2;
(double, int) t1 = (4.5, 3);
Console.WriteLine($"Tuple with elements {t1.Item1} and {t1.Item2}.");
// Output:
// Tuple with elements 4.5 and 3.
(double Sum, int Count) t2 = (4.5, 3);
Console.WriteLine($"Sum of {t2.Count} elements is {t2.Sum}.");
// Output:
// Sum of 3 elements is 4.5.
From Docs: https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/value-tuples
Why not using a multiple returns instead of using tuple
var handler = GenerateFromMethod1(hits);
Process(handler.string1, handler.string1);
private static (string string1, string string2) GenerateFromMethod1()
{
}
I think I would create a class but another alternative is output parameters.
public void GetOrderRelatedIds(out int OrderGroupId, out int OrderTypeId, out int OrderSubTypeId, out int OrderRequirementId)
Since your Tuple only contains integers you could represent it with a Dictionary<string,int>
var orderIds = new Dictionary<string, int> {
{"OrderGroupId", 1},
{"OrderTypeId", 2},
{"OrderSubTypeId", 3},
{"OrderRequirementId", 4}.
};
but I don't recommend that either.
Why is everyone making life so hard. Tuples are for rather temporary data processing. Working with Tuples all the time will make the code very hard to understand at some point. Creating classes for everything could eventually bloat your project.
It's about balance, however...
Your problem seems to be something you would want a class for. And just for the sake of completeness, this class below also contains constructors.
This is the proper pattern for
A custom data type
with no further functionality. Getters and setters can also be expanded with code, getting/setting private members with the name pattern of "_orderGroupId", while also executing functional code.
Including constructors. You can also choose to include just one constructor if all properties are mandatory.
If you want to use all constructors, bubbling like this is the proper pattern to avoid duplicate code.
public class OrderRelatedIds
{
public int OrderGroupId { get; set; }
public int OrderTypeId { get; set; }
public int OrderSubTypeId { get; set; }
public int OrderRequirementId { get; set; }
public OrderRelatedIds()
{
}
public OrderRelatedIds(int orderGroupId)
: this()
{
OrderGroupId = orderGroupId;
}
public OrderRelatedIds(int orderGroupId, int orderTypeId)
: this(orderGroupId)
{
OrderTypeId = orderTypeId;
}
public OrderRelatedIds(int orderGroupId, int orderTypeId, int orderSubTypeId)
: this(orderGroupId, orderTypeId)
{
OrderSubTypeId = orderSubTypeId;
}
public OrderRelatedIds(int orderGroupId, int orderTypeId, int orderSubTypeId, int orderRequirementId)
: this(orderGroupId, orderTypeId, orderSubTypeId)
{
OrderRequirementId = orderRequirementId;
}
}
Or, if you want it really simple: You can also use type initializers:
OrderRelatedIds orders = new OrderRelatedIds
{
OrderGroupId = 1,
OrderTypeId = 2,
OrderSubTypeId = 3,
OrderRequirementId = 4
};
public class OrderRelatedIds
{
public int OrderGroupId;
public int OrderTypeId;
public int OrderSubTypeId;
public int OrderRequirementId;
}
I would write the Item names in the summay..
so by hovering over the function helloworld() the text will say hello = Item1 and world = Item2
helloworld("Hi1,Hi2");
/// <summary>
/// Return hello = Item1 and world Item2
/// </summary>
/// <param name="input">string to split</param>
/// <returns></returns>
private static Tuple<bool, bool> helloworld(string input)
{
bool hello = false;
bool world = false;
foreach (var hw in input.Split(','))
{
switch (hw)
{
case "Hi1":
hello= true;
break;
case "Hi2":
world= true;
break;
}
}
return new Tuple<bool, bool>(hello, world);
}
You Can write a class that contains the Tuple.
You need to override the Equals and GetHashCode functions
and the == and != operators.
class Program
{
public class MyTuple
{
private Tuple<int, int> t;
public MyTuple(int a, int b)
{
t = new Tuple<int, int>(a, b);
}
public int A
{
get
{
return t.Item1;
}
}
public int B
{
get
{
return t.Item2;
}
}
public override bool Equals(object obj)
{
return t.Equals(((MyTuple)obj).t);
}
public override int GetHashCode()
{
return t.GetHashCode();
}
public static bool operator ==(MyTuple m1, MyTuple m2)
{
return m1.Equals(m2);
}
public static bool operator !=(MyTuple m1, MyTuple m2)
{
return !m1.Equals(m2);
}
}
static void Main(string[] args)
{
var v1 = new MyTuple(1, 2);
var v2 = new MyTuple(1, 2);
Console.WriteLine(v1 == v2);
Dictionary<MyTuple, int> d = new Dictionary<MyTuple, int>();
d.Add(v1, 1);
Console.WriteLine(d.ContainsKey(v2));
}
}
will return:
True
True
C# 7 tuple example
var tuple = TupleExample(key, value);
private (string key1, long value1) ValidateAPIKeyOwnerId(string key, string value)
{
return (key, value);
}
if (!string.IsNullOrEmpty(tuple.key1) && tuple.value1 > 0)
{
//your code
}

Casting generic types to subclass

I'm starting with generics types and I'm stuck with my project. Maybe I did not understand generics very well. Explanations have been inserted inline. Basically I need to implement the Do() method but I don't know how to resolve <T2>:
public abstract class MyGenericClass<T> { }
public class MyGenericClass<T, T2> : MyGenericClass<T>
{
public Expression<Func<T, T2>> expression;
public MyGenericClass(Expression<Func<T, T2>> expression)
{
this.expression = expression;
}
}
public class MyClass<T>
{
// I need to mantain a list of my generic class for later use.
// I don't know T2 at this point.
// So I Chose to use Inheritance as a workaround (MyGenericClass<T> and MyGenericClass<T, T2>).
// Maybe it's not a good solution but I counldn't find out other solution.
public List<MyGenericClass<T>> MyGenericList = new List<MyGenericClass<T>>();
// I receive the parametric argument T2 here as part of an Expresion.
// And I keep the expression in my list.
public MyGenericClass<T, T2> ReceivingMethod<T2>(Expression<Func<T, T2>> expression)
{
MyGenericClass<T, T2> genericImp = new MyGenericClass<T, T2>(expression);
MyGenericList.Add(genericImp);
return genericImp;
}
}
public class Client<T>
{
MyClass<T> class1;
// class1 has been created and his field MyGenericList has been populated.
// Then when I call Do()....
public void Do()
{
foreach (var item in class1.MyGenericList)
{
// I need something like this here,
// but it does not compile because I don't know T2 here.
// The caller of Do() method doesn't know T2.
MyGenericClass<T, T2> myGenericItem = (MyGenericClass<T, T2>)item;
var a = myGenericItem.expression;
}
}
}
You have to give Do() the T2 parameter somehow. So my solution is to create a method parameter of the same type. I also nested the types in order to make sure all of them refer to the same T.
I also renamed the parameters to be more descriptive
// T -> TArg
// T2 -> TResult
public abstract class MyBaseClass<TArg>
{
public class MyExpressionClass<TResult> : MyBaseClass<TArg>
{
public Expression<Func<TArg, TResult>> Expression { get; private set; }
public MyExpressionClass(Expression<Func<TArg, TResult>> expression)
{
this.Expression=expression;
}
}
public class MyCollectionClass
{
public List<MyBaseClass<TArg>> MyGenericList = new List<MyBaseClass<TArg>>();
public MyExpressionClass<TResult> ReceivingMethod<TResult>(Expression<Func<TArg, TResult>> expression)
{
var genericImp = new MyExpressionClass<TResult>(expression);
MyGenericList.Add(genericImp);
return genericImp;
}
}
public class Client
{
public MyCollectionClass List = new MyCollectionClass();
public void Do<TResult>()
{
foreach(var item in List.MyGenericList)
{
var expr = item as MyExpressionClass<TResult>;
if(expr!=null)
{
var a = expr.Expression;
Console.WriteLine(a);
}
}
}
}
}
class Program
{
static void Main(string[] args)
{
var client = new MyBaseClass<int>.Client();
// add conversion expressions
client.List.ReceivingMethod((i) => (i).ToString());
client.List.ReceivingMethod((i) => (2*i).ToString());
client.List.ReceivingMethod((i) => (3*i).ToString());
// The programmer has to manually enforce the `string` type
// below based on the results of the expressions above. There
// is no way to enforce consistency because `TResult` can be
// _any_ type.
client.Do<string>();
// Produces the following output
//
// i => i.ToString()
// i => (2*i).ToString()
// i => (3*i).ToString()
}
}
Solution 1 Inspired from #KMoussa comment. I've delegate the responsability to MyGenericClass using an abstract method. This seems a better design. All subclasses will implement this method DoTheWork(). And can be invoked from my Client.Do() method with only T param:
public abstract class MyGenericClass<T>
{
public abstract string DoTheWork();
}
public class MyGenericClass<T, T2> : MyGenericClass<T>
{
public override string DoTheWork()
{
// I can use expression here
}
private Expression<Func<T, T2>> expression { get; set; }
public MyGenericClass(Expression<Func<T, T2>> expression)
{
this.expression = expression;
}
}
public class MyClass<T>
{
public List<MyGenericClass<T>> MyGenericList = new List<MyGenericClass<T>>();
public void ReceivingMethod<T2>(Expression<Func<T, T2>> expression)
{
MyGenericClass<T, T2> genericImp = new MyGenericClass<T, T2>(expression);
}
}
public class Client<T>
{
MyClass<T> class1;
public void Do()
{
// I don't need to cast to MyGenericClass<T, T2>
foreach (MyGenericClass<T> myGenericItem in class1.MyGenericList)
{
string result = myGenericItem.DoTheWork();
}
}
}
Solution 2 Inspired from #ja72 and #juharr comments. Using reflection. First I save the type T2 on MyGenericClass using an abstract property. Then I can invoke a generic method MethodWithArgument using reflection so I can introduce the parameter for the casting:
public abstract class MyGenericClass<T>
{
public abstract Type type { get; set; }
}
public class MyGenericClass<T, T2> : MyGenericClass<T>
{
public Expression<Func<T, T2>> expression { get; set; }
public MyGenericClass(Expression<Func<T, T2>> expression)
{
type = typeof(T2); // I save the type of T2
this.expression = expression;
}
}
public class MyClass<T>
{
public List<MyGenericClass<T>> MyGenericList = new List<MyGenericClass<T>>();
public void ReceivingMethod<T2>(Expression<Func<T, T2>> expression)
{
MyGenericClass<T, T2> genericImp = new MyGenericClass<T, T2>(expression);
}
}
public class Client<T>
{
MyClass<T> class1;
public void Do()
{
foreach (MyGenericClass<T> myGenericItem in class1.MyGenericList)
{
MethodInfo method = GetType().GetMethod("MethodWithArgument");
MethodInfo generic = method.MakeGenericMethod(new Type[] { myGenericItem.type });
string g = (string)generic.Invoke(this, new object[] { myGenericItem });
}
}
// I introduce T2 in this method
public string MethodWithArgument<T2>(MyGenericClass<T> myClass)
{
// Now, the casting is valid
MyGenericClass<T, T2> mySubClass = (MyGenericClass<T, T2>)myClass;
var a = mySubClass.expression;
// I can work with expression here
}
}

C# check object type against multiple types

IS there a way to pass an array of types to the "is" operator?
I am trying to simplify the syntax of checking an object against multiple types.
Something like:
public static function bool IsOfType(object Obj,params Type[] Types)
This would however require the following usage:
if(X.IsOfType(typeof(int),typeof(float))
{...}
I would like to do something like:
if(X is {int,float})
or
if(X.IsOfType(int,float))
or even
public static bool ISOfType<T[]>(this object Obj){...}
if(X.ISOfType<int,float>())
I think they are all impossible.
With C# 10, you can use pattern matching to test an object for multiple types.
Example:
public bool TestObject<T>(T obj)
{
if (obj is not null and (int or float or uint))
{
// obj is not null and guaranteed to be an int, float or uint
}
}
Example 2 (in case you want to use the value):
public bool TestIntOrFloat<T>(T obj)
{
if (obj is not (int or float))
{
// obj is neither int or float
}
else if (obj is int i)
{
// obj is an integer and can be used with the variable 'i'
}
else if (obj is float f)
{
// obj is a floating number and can be used with the variable 'f'
}
}
If you're okay with passing the types as generic arguments, there is a solution. Unfortunately, C# doesn't support variadic generics. You have to define the function for each generic arity.
public static bool IsOfType<T>(this object obj) => obj is T;
public static bool IsOfType<T1, T2>(this object obj) => obj is T1 || obj is T2;
public static bool IsOfType<T1, T2, T3>(this object obj) => obj is T1 || obj is T2 || obj is T3;
public static bool IsOfType<T1, T2, T3, T4>(this object obj) => obj is T1 || obj is T2 || obj is T3 || obj is T4;
public static bool IsOfType<T1, T2, T3, T4, T5>(this object obj) => obj is T1 || obj is T2 || obj is T3 || obj is T4 || obj is T5;
public static bool IsOfType<T1, T2, T3, T4, T5, T6>(this object obj) => obj is T1 || obj is T2 || obj is T3 || obj is T4 || obj is T5 || obj is T6;
public static bool IsOfType<T1, T2, T3, T4, T5, T6, T7>(this object obj) => obj is T1 || obj is T2 || obj is T3 || obj is T4 || obj is T5 || obj is T6 || obj is T7;
public static bool IsOfType<T1, T2, T3, T4, T5, T6, T7, T8>(this object obj) => obj is T1 || obj is T2 || obj is T3 || obj is T4 || obj is T5 || obj is T6 || obj is T7 || obj is T8;
I doubt you'll need more than 8 types but if you do, just define more overloads.
It can looks crazy, but you can use the following Fluent syntax:
object someInstance = 5.0;
if(someInstance
.Is<int>()
.Or<double>()) {
// ...
}
Here the fluent-syntax is implemented as follows:
static class FluentIs {
public static IsResult Is<T>(this object target) {
return new IsResult(target, () => target is T);
}
public static IsResult Or<T>(this IsResult prev) {
return new IsResult(prev, (v, x) => v || (x is T));
}
public class IsResult {
Func<bool> value;
object target;
internal IsResult(IsResult r, Func<bool, object, bool> getValue) :
this(r.target, () => getValue(r.value(), r.target)) {
}
internal IsResult(object target, Func<bool> value) {
this.target = target;
this.value = value;
}
// bool Operators
public static bool operator true(IsResult r) { return r.value(); }
public static bool operator false(IsResult r) { return !r.value(); }
}
}
My "chosen" solution was to use my handy "In" extension function to validate based on object type name.
public static bool IsAnyOf(this object Obj,params string[] TypeNames)
{
return Obj.GetType().Name.In(TypeNames);
}
public static bool In(this string Needle,params string [] Haystack)
{
foreach (string straw in Haystack)
if (straw == Needle)
return true;
return false;
}
Usage:
public static void CheckAll(this TreeNode Node)
{
foreach(TreeNode Child in Node.Nodes)
{
if(Child.GetType().Name.In("ChildTablesNode","ChildTableNode"))
{
Child.Checked = Node.Checked;
Child.CheckAll();
}
}
}
private void ctxTree_Opening(object sender, CancelEventArgs e)
{
TreeNode nSelected = Tree.SelectedNode;
ctxScript.Visible = !nSelected.IsAnyOf("TablesNode"
, "ViewsNode"
, "ProceduresNode"
, "UserTableTypesNode"
, "FunctionsNode"
, "ServerNode"
, "DatabaseNode"
, "ColumnsNode"
, "ColumnNode"
, "TriggersNode");
Type[] x = { typeof(int) };
}

Implementing the Choice Type in C#

for educational reasons I'm trying to implement the Choice and the Option Type from F# in C#. This was inspired by the book "Real World Functional Programming" and some blog posts like: http://bugsquash.blogspot.de/2011/08/refactoring-to-monadic-c-applicative.html and http://tomasp.net/blog/idioms-in-linq.aspx/.
I would like to get this to work, but I don't know how to implement the Extensions for the Choice Type (Bind, Map, SelectMany, ...):
public static void Division()
{
Console.WriteLine("Enter two (floating point) numbers:");
(
from f1 in ReadDouble().ToChoice("Could not parse input to a double.")
from f2 in ReadDouble().ToChoice("Could not parse input to a double.")
from result in Divide(f1, f2).ToChoice("Cannot divide by zero.")
select result
)
.Match(
x => Console.WriteLine("Result = {0}", x),
x => Console.WriteLine("Error: {0}", x));
}
public static Option<double> Divide(double a, double b)
{
return b == 0 ? Option.None<double>() : Option.Some(a / b);
}
public static Option<Double> ReadDouble()
{
double i;
if (Double.TryParse(Console.ReadLine(), out i))
return Option.Some(i);
else
return Option.None<double>();
}
public static Option<int> ReadInt()
{
int i;
if (Int32.TryParse(Console.ReadLine(), out i))
return Option.Some(i);
else
return Option.None<int>();
}
}
The Option Type looks like this:
public enum OptionType
{
Some, None
}
public abstract class Option<T>
{
private readonly OptionType _tag;
protected Option(OptionType tag)
{
_tag = tag;
}
public OptionType Tag { get { return _tag; } }
internal bool MatchNone()
{
return Tag == OptionType.None;
}
internal bool MatchSome(out T value)
{
value = Tag == OptionType.Some ? ((Some<T>)this).Value : default(T);
return Tag == OptionType.Some;
}
public void Match(Action<T> onSome, Action onNone)
{
if (Tag == OptionType.Some)
onSome(((Some<T>)this).Value);
else
onNone();
}
public Choice<T, T2> ToChoice<T2>(T2 value)
{
if (Tag == OptionType.Some)
{
T some;
MatchSome(out some);
return Choice.NewChoice1Of2<T, T2>(some);
}
else
return Choice.NewChoice2Of2<T, T2>(value);
}
}
internal class None<T> : Option<T>
{
public None() : base(OptionType.None) { }
}
internal class Some<T> : Option<T>
{
public Some(T value)
: base(OptionType.Some)
{
_value = value;
}
private readonly T _value;
public T Value { get { return _value; } }
}
public static class Option
{
public static Option<T> None<T>()
{
return new None<T>();
}
public static Option<T> Some<T>(T value)
{
return new Some<T>(value);
}
}
public static class OptionExtensions
{
public static Option<TResult> Map<T, TResult>(this Option<T> source, Func<T, TResult> selector)
{
T value;
return source.MatchSome(out value) ? Option.Some(selector(value)) : Option.None<TResult>();
}
public static Option<TResult> Bind<T, TResult>(this Option<T> source, Func<T, Option<TResult>> selector)
{
T value;
return source.MatchSome(out value) ? selector(value) : Option.None<TResult>();
}
public static Option<TResult> Select<T, TResult>(this Option<T> source, Func<T, TResult> selector)
{
return source.Map(selector);
}
public static Option<TResult> SelectMany<TSource, TValue, TResult>(this Option<TSource> source, Func<TSource, Option<TValue>> valueSelector, Func<TSource, TValue, TResult> resultSelector)
{
return source.Bind(s => valueSelector(s).Map(v => resultSelector(s, v)));
}
}
And here is the Choice Type Implementation:
public enum ChoiceType { Choice1Of2, Choice2Of2 };
public abstract class Choice<T1, T2>
{
private readonly ChoiceType _tag;
protected Choice(ChoiceType tag)
{
_tag = tag;
}
public ChoiceType Tag { get { return _tag; } }
internal bool MatchChoice1Of2(out T1 value)
{
value = Tag == ChoiceType.Choice1Of2 ? ((Choice1Of2<T1, T2>)this).Value : default(T1);
return Tag == ChoiceType.Choice1Of2;
}
internal bool MatchChoice2Of2(out T2 value)
{
value = Tag == ChoiceType.Choice2Of2 ? ((Choice2Of2<T1, T2>)this).Value : default(T2);
return Tag == ChoiceType.Choice2Of2;
}
public void Match(Action<T1> onChoice1Of2, Action<T2> onChoice2Of2)
{
if (Tag == ChoiceType.Choice1Of2)
onChoice1Of2(((Choice1Of2<T1, T2>)this).Value);
else
onChoice2Of2(((Choice2Of2<T1, T2>)this).Value);
}
}
internal class Choice1Of2<T1, T2> : Choice<T1, T2>
{
public Choice1Of2(T1 value)
: base(ChoiceType.Choice1Of2)
{
_value = value;
}
private readonly T1 _value;
public T1 Value { get { return _value; } }
}
internal class Choice2Of2<T1, T2> : Choice<T1, T2>
{
public Choice2Of2(T2 value)
: base(ChoiceType.Choice2Of2)
{
_value = value;
}
private readonly T2 _value;
public T2 Value { get { return _value; } }
}
public static class Choice
{
public static Choice<T1, T2> NewChoice1Of2<T1, T2>(T1 value)
{
return new Choice1Of2<T1, T2>(value);
}
public static Choice<T1, T2> NewChoice2Of2<T1, T2>(T2 value)
{
return new Choice2Of2<T1, T2>(value);
}
}
EDIT:
It actually works with the Extensions below. What I don't really like about it is that this implementation adds a context specific behaviour to the Choice type. This is because the Choice1Of2 is the prefered choice because all the extension methods mainly operate on it rather than on Choice2Of2 or both. (But that's what the consuming code actually implies, so I guess it is the only way to get it working.)
public static Choice<TResult, T2> Map<T1, T2, TResult>(this Choice<T1, T2> source, Func<T1, TResult> selector)
{
T1 value1;
if(source.MatchChoice1Of2(out value1))
{
return Choice.NewChoice1Of2<TResult, T2>(selector(value1));
}
T2 value2;
if (source.MatchChoice2Of2(out value2))
{
return Choice.NewChoice2Of2<TResult, T2>(value2);
}
throw new InvalidOperationException("source (:Choice) has no value.");
}
public static Choice<TResult, T2> Bind<T1, T2, TResult>(this Choice<T1, T2> source, Func<T1, Choice<TResult, T2>> selector)
{
T1 value1;
if (source.MatchChoice1Of2(out value1))
{
return selector(value1);
}
T2 value2;
if (source.MatchChoice2Of2(out value2))
{
return Choice.NewChoice2Of2<TResult, T2>(value2);
}
throw new InvalidOperationException("source (:Choice) has no value.");
}
public static Choice<TResult, T2> Select<T1, T2, TResult>(this Choice<T1, T2> source, Func<T1, TResult> selector)
{
return source.Map(selector);
}
public static Choice<TResult, T2> SelectMany<TSource, TValue, T2, TResult>(this Choice<TSource, T2> source, Func<TSource, Choice<TValue, T2>> valueSelector, Func<TSource, TValue, TResult> resultSelector)
{
return source.Bind(s => valueSelector(s).Map(v => resultSelector(s, v)));
}
Since Choice has two type parameters, you need to fix the first one to be able to write Select and SelectMany (bind):
public abstract class Choice<T1, T2>
{
public abstract Choice<T1, T3> Select<T3>(Func<T2, T3> f);
public abstract Choice<T1, T3> SelectMany<T3>(Func<T2, Choice<T1, T3>> f);
}
their implementation is straightforward for Choice1Of2:
public override Choice<T1, T3> Select<T3>(Func<T2, T3> f)
{
return new Choice1Of2<T1, T3>(this._value);
}
public override Choice<T1, T3> SelectMany<T3>(Func<T2, Choice<T1, T3>> f)
{
return new Choice1Of2<T1, T3>(this._value);
}
and for Choice2Of2 you just need to provide the inner value to the given function:
public override Choice<T1, T3> Select<T3>(Func<T2, T3> f)
{
return new Choice2Of2<T1, T3>(f(this.Value));
}
public override Choice<T1, T3> SelectMany<T3>(Func<T2, Choice<T1, T3>> f)
{
return f(this._value);
}
You may also want a BiSelect function for mapping over both type parameters:
public abstract BiSelect<T3, T4>(Func<T1, T3> ff, Func<T2, T4> fs);
If you want to use SelectMany with the linq query syntax, you need to implement another overload which looks like:
public abstract Choice<T1, T4> SelectMany<T3, T4>(Func<T2, Choice<T1, T3>> f, Func<T2, T3, T4> selector);
The implementation for Choice1Of2 is similar to before:
public override Choice<T1, T4> SelectMany<T3, T4>(Func<T2, Choice<T1, T3>> f, Func<T2, T3, T4> selector)
{
return new Choice1Of2<T1, T4>(this._value);
}
The implementation for Choice2Of2 is then:
public override Choice<T1, T4> SelectMany<T3, T4>(Func<T2, Choice<T1, T3>> f, Func<T2, T3, T4> selector)
{
T2 val = this._value;
var e = f(val);
return e.Select(v => selector(val, v));
}
and you can do:
var choice = from x in new Choice2Of2<string, int>(1)
from y in new Choice2Of2<string, int>(4)
select x + y;
Here is one new extensions class to make 'Match' method works on IEnumerable
public static class ChoiceExtensions
{
// You need this method, because code 'select result' is a LINQ expression and it returns IEnumerable
public static void Match<T1, T2>(this IEnumerable<Choice<T1, T2>> seq, Action<T1> onChoice1Of2, Action<T2> onChoice2Of2)
{
foreach (var choice in seq)
{
choice.Match(onChoice1Of2, onChoice2Of2);
}
}
// This method will help with the complex matching
public static Choice<T1, T2> Flat<T1, T2>(this Choice<Choice<T1, T2>, T2> choice)
{
Choice<T1, T2> result = null;
choice.Match(
t1 => result = t1,
t2 => result = new Choice2Of2<T1, T2>(t2));
return result;
}
}
Also, I've changed your Choice class:
// Implement IEnumerable to deal with LINQ
public abstract class Choice<T1, T2> : IEnumerable<Choice<T1, T2>>
{
IEnumerator<Choice<T1, T2>> IEnumerable<Choice<T1, T2>>.GetEnumerator()
{
yield return this;
}
public IEnumerator GetEnumerator()
{
yield return this;
}
// These two methods work with your Devide function
// I think, it is good to throw an exception here, if c is not a choice of 1
public static implicit operator T1(Choice<T1, T2> c)
{
T1 val;
c.MatchChoice1Of2(out val);
return val;
}
// And you can add exception here too
public static implicit operator T2(Choice<T1, T2> c)
{
T2 val;
c.MatchChoice2Of2(out val);
return val;
}
// Your Match method returns void, it is not good in functional programming,
// because, whole purpose of the method returning void is the change state,
// and in FP state is immutable
// That's why I've created PureMatch method for you
public Choice<T1Out, T2Out> PureMatch<T1Out, T2Out>(Func<T1, T1Out> onChoice1Of2, Func<T2, T2Out> onChoice2Of2)
{
Choice<T1Out, T2Out> result = null;
Match(
t1 => result = new Choice1Of2<T1Out, T2Out>(onChoice1Of2(t1)),
t2 => result = new Choice2Of2<T1Out, T2Out>(onChoice2Of2(t2)));
return result;
}
// Continue Choice class
}
Your sample is slightly incorrect, because when you write:
from f1 in ReadDouble().ToChoice("Could not parse input to a double.")
from f2 in ReadDouble().ToChoice("Could not parse input to a double.")
from result in Devide(f1, f2).ToChoice("Cannot devide by zero.")
select result
in the last line you actually ignore f1 and f2. So it is impossible to see parsing error. Better write:
(
from f1 in ReadDouble().ToChoice("Could not parse input to a double.")
from f2 in ReadDouble().ToChoice("Could not parse input to a double.")
from result in
f1.PureMatch(
f1value => f2.PureMatch(
f2value => Devide(f1, f2).ToChoice("Cannot devide by zero."),
f2err => f2err).Flat(),
f1err => f1err
).Flat()
select result
)
.Match(
x => Console.WriteLine("Result = {0}", x),
x => Console.WriteLine("Error: {0}", x));
You can create nice helper methods to deal with this complicated stuff, something like PureMatch method but with more arguments

Categories