In the following code I am trying to accomplish default type deduction in a factory pattern. I would like to call the factory method with an arbitrary combination of arguments and have the generic type parameters inferred from the default parameters for the omitted arguments. This attempt at that, however, results in error CS1750. CS1750 is mentioned in a handful of places in the roslyn repo, but reviewing those didn't reveal much about the cause in this case.
The full text of the error is as follows:
(parameter) S a = new S()
A value of type 'S' cannot be used as a default parameter because there are no standard conversions to type 'S' [TypeInference]csharp(CS1750)
public class T {}
public class T0 : T {}
public class T1 : T {}
// T2{} .. T9{}
public class T10 : T {}
public struct S<T> {}
public class X {} // X is a complex object strongly-typed with T1..T10
public static class C {
public static X Factory<A,B/*,C..J*/>(
S<T0> s = new S<T0>(), // this is fine
S<A> a = new S<T0>(), // ERROR: no standard conversions to type...
S<B> b = new S<T0>() // ...'S<A>' [TypeInference]csharp(CS1750)
//S<C> c,
//...
//S<J> j
)
where A : T
where B : T
=>throw new System.NotImplementedException();
static void usage1() {
/* I'd like to be able to omit an arbitrary portion
of the factory arguments and have type inference use
the default values.*/
Factory(b : new S<T1>());
}
// simplified example
public static void Foo<A>(A a) {}
public static void Bar<A>(A a=42) {} // ERROR: CS1750
static void usage2() {
Foo(42); // this is fine
}
}
I have been trying to understand why CS1750 is raised. According to the 5th edition of the spec
15.6.2 Method Parameters...
The expression in a default-argument shall be one of the following: ...
- an expression of the form new S() where S is a value type
new S<T0>() seem to meet this criterion. Indeed, the parameter declaration S<T0> s = new S<T0>() doesn't seem to raise an error.
Reading (admittedly without completely absorbing) the spec's type inference section it wasn't obvious why default values wouldn't be considered during type inference. The language in that section even seems to be careful to distinguish optional parameters with and without corresponding arguments. For example, in this sentence a missing optional argument is excluded as cause for inference failure:
12.6.3 Type Inference...
If ... there is a non-optional parameter with no corresponding argument, then inference immediately fails.
Rather than rule out default parameters, this seems more like a weak suggestion that type inference could be based on them.
- Why is the compiler trying to convert
S<T0>toS<A>instead of inferringAto beT0? - Does the spec prohibit type inference based on default parameters?