Predecessor: #5023
Actually in the parent issue, pattern matching was not highlighted. Hence this new issue. Given these classes-
abstract class Result<T> { }
sealed class Success<T>:Result<T>
{
public T Value {get;}
public Success(T value) {Value = value;}
}
sealed class Error<T>:Result<T>
{
public Exception Ex {get;}
public Error(Exception ex) {Ex = ex;}
}
And this static method-
static Result<T> Try<T>(Func<T> fun)
{
try
{
return new Success<T>(fun());
}
catch (Exception e)
{
return new Error<T>(e);
}
}
I want to write
var res = Try(SomeMethod);
if (res is Success ok)
Console.WriteLine(ok.Value);
else
Console.WriteLine((res as Error).Ex.Message);
instead of
var res = Try(SomeMethod);
if (res is Success<int> ok)
Console.WriteLine(ok.Value);
else
Console.WriteLine((res as Error<int>).Ex.Message);
Another option can be discarding the type with '_'-
var res = Try(SomeMethod);
if (res is Success<_> ok)
Console.WriteLine(ok.Value);
else
Console.WriteLine((res as Error<_>).Ex.Message);
Look at #6739, specifically the use of enums as algebraic data types. The Option<T> example is very similar to your Result<T> use case.
Assuming that syntax is adopted as-is, you'd probably work with it as follows:
public enum class Result<T> {
Success(T result),
Error(Exception error)
}
Result<T> result = ...; // calculate some result here
if (result is Success(var value)) { ... }
else if (result is Error(var error)) { ... }
Is the pattern matching with generic types coming included with it?
That proposal won't be implemented for C# 7.0, which is more or less feature complete now. I expect that pattern matching will be expanded upon over several releases of the language, hopefully more point releases than new versions.
@gulshan Can you please show what kind of code the compiler would translate this into?
I keep seeing the title and thinking "ooh, genetic types, what's that?"
@gafter I'm not sure if this can be done with code generation. Now I realize there may be several steps for this proposal-
is operator working with the bare generic types- instead of requiring them to specify type arguments. From my example, that will make result is Success a valid expression instead of requiring result is Success<int> or throwing Error CS0305.as operator, infering the type argument. result as Success should be infered to (or code generated to) result as Success<int> infering the int as the type argument.result is Success ok code generated to result is Success<int> ok.@gulshan
The "bare" generic type for Success<int> would be Success<T> or Success<>, not Success. Success would be a completely different type.
// all legal and different types
public class Success { }
public class Success<T> { }
public class Success<T1, T2> { }
For the C# compiler to assume that Success meant Success<T> or Success<T1, T2> would lead to all kinds of ambiguity problems.
Then it can be Success<_> as stated at the end of my proposal, or Success<*>. But I really want it to be parameterless Success, if the ambiguity is somehow resolvable- like prioritizing types with less (or no) generic type parameters.
I keep seeing the title and thinking "ooh, genetic types, what's that?"
@jnm2 Genetic types are great for inheritance.
Discussion is on- https://github.com/dotnet/csharplang/issues/268
Most helpful comment
@jnm2 Genetic types are great for inheritance.