C
C#•2y ago
Xan.Nava

How to use Tuple in generic class?

So I know you can use Tuple<Type, Func<object>> for example, but is there any way to just use (Type type, Func<Object> obj)? Or even give Tuple<> names so it isn't Item1, Item2? I imagine if this isn't implemented it has to do with how the () tuple works at compile, but I would think it is easy enough on compile time to just do .ToTuple() wherever it would be needed.
20 Replies
Klarth
Klarth•2y ago
You should typically avoid Tuple<...> as it's the old reference type. Use ValueTuple<...> with the newer syntax. eg. (Type Type, Func<object> Function) tuple = (typeof(Program), () => 5); Unfortunately, I don't think you can use var here and name the right-hand side. https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/value-tuples#tuple-field-names You could otherwise in tuples that don't have lambdas.
Klarth
Klarth•2y ago
You get this error if you try only the RHS.
Chiyoko_S
Chiyoko_S•2y ago
there is a tuple notation in C# that you can use, but that is not Tuple<>, it's actually ValueTuple<> (which for our purposes should do the same thing) and you can actually use var and name elements from the RHS (Type: a, Function: b)
Xan.Nava
Xan.Nava•2y ago
Not sure how to do that with Generic. For example
public interface Iam<T, TR> {
public T TestMethod(TR value);
}

public class ClassName : Iam<Type, ValueTuple<int, string>> {
public Type TestMethod((int, string) value) {
// Do Stuff

return value.Item1.GetType();
}
}
public interface Iam<T, TR> {
public T TestMethod(TR value);
}

public class ClassName : Iam<Type, ValueTuple<int, string>> {
public Type TestMethod((int, string) value) {
// Do Stuff

return value.Item1.GetType();
}
}
Is what I am getting with ValueType, but if I put (itn: age, string: name) it throws errors.
Chiyoko_S
Chiyoko_S•2y ago
well what is the actual code that shows error and what error
Xan.Nava
Xan.Nava•2y ago
public Type TestMethod((int value, string name) value)
public Type TestMethod((int value, string name) value)
throws
Severity Code Description Project File Line Suppression State
Error CS8141 The tuple element names in the signature of method 'ClassName.TestMethod((int value, string name))' must match the tuple element names of interface method 'Iam<Type, (int, string)>.TestMethod((int, string))' (including on the return type). UniversalUnity F:\sys0\DreamScaping_Unity\Assets\Packages_Internal\Levels\UniversalUnity\Level1\Physics\Collisions\Collisions.Interchange.cs 276 Active
Severity Code Description Project File Line Suppression State
Error CS8141 The tuple element names in the signature of method 'ClassName.TestMethod((int value, string name))' must match the tuple element names of interface method 'Iam<Type, (int, string)>.TestMethod((int, string))' (including on the return type). UniversalUnity F:\sys0\DreamScaping_Unity\Assets\Packages_Internal\Levels\UniversalUnity\Level1\Physics\Collisions\Collisions.Interchange.cs 276 Active
Klarth
Klarth•2y ago
I would use a concrete type there, not a tuple. Especially in Unity where C# is weaker.
Xan.Nava
Xan.Nava•2y ago
Severity Code Description Project File Line Suppression State
Error CS0246 The type or namespace name 'age' could not be found (are you missing a using directive or an assembly reference?) UniversalUnity F:\sys0\DreamScaping_Unity\Assets\Packages_Internal\Levels\UniversalUnity\Level1\Physics\Collisions\Collisions.Interchange.cs 276 Active
Severity Code Description Project File Line Suppression State
Error CS0246 The type or namespace name 'age' could not be found (are you missing a using directive or an assembly reference?) UniversalUnity F:\sys0\DreamScaping_Unity\Assets\Packages_Internal\Levels\UniversalUnity\Level1\Physics\Collisions\Collisions.Interchange.cs 276 Active
is for
public Type TestMethod((int: age, string: name) value)
public Type TestMethod((int: age, string: name) value)
blokyk
blokyk•2y ago
It's because ValueTuple<int, string> is not quite the same as (int value, string name) so you need to write
public class ClassName : Iam<Type, (int value, string name)>
{ ... }
public class ClassName : Iam<Type, (int value, string name)>
{ ... }
Xan.Nava
Xan.Nava•2y ago
Ah yep that is working now. Not sure where I was bonking it up yesterday 😆
public class ClassName : Iam<Type, (int age, string name)>
public class ClassName : Iam<Type, (int age, string name)>
Chiyoko_S
Chiyoko_S•2y ago
I think it's really just complaining why you don't have names matched up yeah
Xan.Nava
Xan.Nava•2y ago
I am working in unity so maybe the (int: age, string: name) is a newer C# way? the (int age, string name) works fine.
Chiyoko_S
Chiyoko_S•2y ago
no it's like two different things I think I understood your question as 'how to name tuple elements on construction using var' in which case you can do var a = (Name: "hello", Age: 20);
blokyk
blokyk•2y ago
i don't think (int: arg, string: name) is valid for a declaration, and even if it was var t = (int: age, string: name) where age and name already exists, int and strings are keywords so it wouldn't work
Xan.Nava
Xan.Nava•2y ago
Cool cool, thanks for the help!
Chiyoko_S
Chiyoko_S•2y ago
also Klarth's point is valid, tuples can be fine for some one-off stuffs but they get kinda long and cumbersome (somewhat) if you end up using it a lot records could be an alternative
blokyk
blokyk•2y ago
i mean if they're using unity, they probably don't have records :/
Chiyoko_S
Chiyoko_S•2y ago
oh crap runs
blokyk
blokyk•2y ago
ye unity isn't great lol
Xan.Nava
Xan.Nava•2y ago
Yeah I am using it for some generic stuff that doesn't need a full command struct for the args, but need different number of args per inheritor.