Problems with C# type inference mechanism for extension methods
I´m trying to create an API in C# to evaluate dependent analytics by resolving its dependency tree and treating caching, and other issues in the background.
I´ll not delve into details here, bug I´m struggling with C# type inference mechanism.
for starters. suppose I have these classes:
public interface IAnalytic {}
public interface IAnalytic<TInput, TOutput> : IAnalytic
{
TOutput Calculate(TInput input);
}
public interface IAnalyticResolver <T> where T: IAnalytic
{
object EvaluateUntyped();
}
public interface IResolver
{
IAnalyticResolver<TAnalyticImpl> GetResolver<TAnalyticImpl> () where TAnalyticImpl : IAnalytic;
}
in a way that if I have a class such as this:
public class ParseAnalytic : IAnalytic<string, int>
{
public int Calculate(string input) => int.Parse(input);
}
I can call my API as:
IResolver r = //..
int result = (int)r.GetResolver<ParseAnalytic>().EvaluateUntyped();
However, I really dislike having to type cast my result at the end. So I´ve tried to create an extension method to work around this issue:
public static class ResolverExtensions
{
public static TOutput Evaluate<TAnalytic, TInput, TOutput>(this IAnalyticResolver<TAnalytic> resolver)
where TAnalytic : IAnalytic<TInput, TOutput>
{
return (TOutput)resolver.EvaluateUntyped();
}
}
I was expecting that by calling this method, C# would be able to infer the TOutput
type because of the parameter IAnalyticResolver<TAnalytic>
with the restriction where TAnalytic : IAnalytic<TInput, TOutput>
However that is not the case, when I try to use:
int i = r.GetResolver<ParseAnalytic>().Evaluate();
I get an
CS0411 The type arguments for method 'ResolverExtensions.Evaluate(IAnalyticResolver)' cannot be inferred from the usage. Try specifying the type arguments explicitly.
I think I understand why this is happening (TAnalytic
could be implementing multiple IAnalytic<,>
interfaces)
Is there a work around this issue ?, Or do will I have to explicitly call the extension method with the type arguments? (that would not be very user friendly)
c#
add a comment |
I´m trying to create an API in C# to evaluate dependent analytics by resolving its dependency tree and treating caching, and other issues in the background.
I´ll not delve into details here, bug I´m struggling with C# type inference mechanism.
for starters. suppose I have these classes:
public interface IAnalytic {}
public interface IAnalytic<TInput, TOutput> : IAnalytic
{
TOutput Calculate(TInput input);
}
public interface IAnalyticResolver <T> where T: IAnalytic
{
object EvaluateUntyped();
}
public interface IResolver
{
IAnalyticResolver<TAnalyticImpl> GetResolver<TAnalyticImpl> () where TAnalyticImpl : IAnalytic;
}
in a way that if I have a class such as this:
public class ParseAnalytic : IAnalytic<string, int>
{
public int Calculate(string input) => int.Parse(input);
}
I can call my API as:
IResolver r = //..
int result = (int)r.GetResolver<ParseAnalytic>().EvaluateUntyped();
However, I really dislike having to type cast my result at the end. So I´ve tried to create an extension method to work around this issue:
public static class ResolverExtensions
{
public static TOutput Evaluate<TAnalytic, TInput, TOutput>(this IAnalyticResolver<TAnalytic> resolver)
where TAnalytic : IAnalytic<TInput, TOutput>
{
return (TOutput)resolver.EvaluateUntyped();
}
}
I was expecting that by calling this method, C# would be able to infer the TOutput
type because of the parameter IAnalyticResolver<TAnalytic>
with the restriction where TAnalytic : IAnalytic<TInput, TOutput>
However that is not the case, when I try to use:
int i = r.GetResolver<ParseAnalytic>().Evaluate();
I get an
CS0411 The type arguments for method 'ResolverExtensions.Evaluate(IAnalyticResolver)' cannot be inferred from the usage. Try specifying the type arguments explicitly.
I think I understand why this is happening (TAnalytic
could be implementing multiple IAnalytic<,>
interfaces)
Is there a work around this issue ?, Or do will I have to explicitly call the extension method with the type arguments? (that would not be very user friendly)
c#
add a comment |
I´m trying to create an API in C# to evaluate dependent analytics by resolving its dependency tree and treating caching, and other issues in the background.
I´ll not delve into details here, bug I´m struggling with C# type inference mechanism.
for starters. suppose I have these classes:
public interface IAnalytic {}
public interface IAnalytic<TInput, TOutput> : IAnalytic
{
TOutput Calculate(TInput input);
}
public interface IAnalyticResolver <T> where T: IAnalytic
{
object EvaluateUntyped();
}
public interface IResolver
{
IAnalyticResolver<TAnalyticImpl> GetResolver<TAnalyticImpl> () where TAnalyticImpl : IAnalytic;
}
in a way that if I have a class such as this:
public class ParseAnalytic : IAnalytic<string, int>
{
public int Calculate(string input) => int.Parse(input);
}
I can call my API as:
IResolver r = //..
int result = (int)r.GetResolver<ParseAnalytic>().EvaluateUntyped();
However, I really dislike having to type cast my result at the end. So I´ve tried to create an extension method to work around this issue:
public static class ResolverExtensions
{
public static TOutput Evaluate<TAnalytic, TInput, TOutput>(this IAnalyticResolver<TAnalytic> resolver)
where TAnalytic : IAnalytic<TInput, TOutput>
{
return (TOutput)resolver.EvaluateUntyped();
}
}
I was expecting that by calling this method, C# would be able to infer the TOutput
type because of the parameter IAnalyticResolver<TAnalytic>
with the restriction where TAnalytic : IAnalytic<TInput, TOutput>
However that is not the case, when I try to use:
int i = r.GetResolver<ParseAnalytic>().Evaluate();
I get an
CS0411 The type arguments for method 'ResolverExtensions.Evaluate(IAnalyticResolver)' cannot be inferred from the usage. Try specifying the type arguments explicitly.
I think I understand why this is happening (TAnalytic
could be implementing multiple IAnalytic<,>
interfaces)
Is there a work around this issue ?, Or do will I have to explicitly call the extension method with the type arguments? (that would not be very user friendly)
c#
I´m trying to create an API in C# to evaluate dependent analytics by resolving its dependency tree and treating caching, and other issues in the background.
I´ll not delve into details here, bug I´m struggling with C# type inference mechanism.
for starters. suppose I have these classes:
public interface IAnalytic {}
public interface IAnalytic<TInput, TOutput> : IAnalytic
{
TOutput Calculate(TInput input);
}
public interface IAnalyticResolver <T> where T: IAnalytic
{
object EvaluateUntyped();
}
public interface IResolver
{
IAnalyticResolver<TAnalyticImpl> GetResolver<TAnalyticImpl> () where TAnalyticImpl : IAnalytic;
}
in a way that if I have a class such as this:
public class ParseAnalytic : IAnalytic<string, int>
{
public int Calculate(string input) => int.Parse(input);
}
I can call my API as:
IResolver r = //..
int result = (int)r.GetResolver<ParseAnalytic>().EvaluateUntyped();
However, I really dislike having to type cast my result at the end. So I´ve tried to create an extension method to work around this issue:
public static class ResolverExtensions
{
public static TOutput Evaluate<TAnalytic, TInput, TOutput>(this IAnalyticResolver<TAnalytic> resolver)
where TAnalytic : IAnalytic<TInput, TOutput>
{
return (TOutput)resolver.EvaluateUntyped();
}
}
I was expecting that by calling this method, C# would be able to infer the TOutput
type because of the parameter IAnalyticResolver<TAnalytic>
with the restriction where TAnalytic : IAnalytic<TInput, TOutput>
However that is not the case, when I try to use:
int i = r.GetResolver<ParseAnalytic>().Evaluate();
I get an
CS0411 The type arguments for method 'ResolverExtensions.Evaluate(IAnalyticResolver)' cannot be inferred from the usage. Try specifying the type arguments explicitly.
I think I understand why this is happening (TAnalytic
could be implementing multiple IAnalytic<,>
interfaces)
Is there a work around this issue ?, Or do will I have to explicitly call the extension method with the type arguments? (that would not be very user friendly)
c#
c#
edited Nov 13 '18 at 11:35
Uwe Keim
27.4k31128210
27.4k31128210
asked Nov 13 '18 at 11:33
Fabio MarrecoFabio Marreco
1,1361314
1,1361314
add a comment |
add a comment |
2 Answers
2
active
oldest
votes
Not sure this is exactly what you are looking for but here's how you only need to specify the type of the resolver during instantiation or in an implementation (you can't avoid specification/casts altogether):
public interface IAnalytic { }
public interface IAnalytic<TInput, TOutput> : IAnalytic
{
TOutput Calculate(TInput input);
}
public interface IAnalyticResolver<T, TOutput> where T : IAnalytic
{
TOutput Evaluate();
}
public interface IResolver<TOutput>
{
IAnalyticResolver<TAnalyticImpl, TOutput> GetResolver<TAnalyticImpl>() where TAnalyticImpl : IAnalytic;
}
public class ParseAnalytic : IAnalytic<string, int>
{
public int Calculate(string input) => int.Parse(input);
}
public class IntResolver : IResolver<int>
{
public IAnalyticResolver<TAnalyticImpl, int> GetResolver<TAnalyticImpl>() where TAnalyticImpl : IAnalytic
{
throw new NotImplementedException();
}
}
class Program
{
static void Main(string args)
{
IResolver<int> r = new IntResolver();
int result = r.GetResolver<ParseAnalytic>().Evaluate();
}
}
Thanks, that helps, however I was wanted to leave the inference of the Output type to the call. because I wanted to have many calls tor.GetResolver<...>.Evaluate()
each returning the correct type.
– Fabio Marreco
Nov 13 '18 at 16:09
Yeah I see. I think the issue is that you don't know them because you can't tell if you are dealing with IAnalytic or IAnalytic<TInput, TOutput>. When I remove IAnalytic it does work but then you have to specify all the types everywhere. Maybe it would help if you gave me some implementations of it all for a specific use case. Could you share one?
– fstam
Nov 13 '18 at 17:42
add a comment |
Thanks everyone,
But I ended up creating a intermediary interface such as
public interface IAnalytic<TOutput> : IAnalytic { }
and making IAnalytic<,>
inherit from it:
public interface IAnalytic<TInput, TOutput> : IAnalytic<TOutput>
{
TOutput Calculate(TInput input);
}
And also changed the IAnalyticResolverInterface
to work with it:
public interface IAnalyticResolver<TAnalytic, TOutput> where TAnalytic : IAnalytic<TOutput>
{
TOutput Evaluate();
}
public interface IResolver
{
IAnalyticResolver<TAnalyticImpl, TOutput> GetResolver<TAnalyticImpl, TOutput> ()
where TAnalyticImpl : IAnalytic<TOutput>;
}
with this, I can call the resolver returning the correct type. However, I have to explicitly state the TOutput
type.
int i = r.GetResolver<ParseAnalytic, int>().Evaluate();
this is redundant, since ParseAnalytic
already is a IAnalytic<string, int>
. But I can cope with that because at least int
is the only acceptable type in this situation. If I try to write something like
double i = r.GetResolver<ParseAnalytic, double>().Evaluate();
the compiler will say:
CS0311 The type 'UserQuery.ParseAnalytic' cannot be used as type parameter 'TAnalyticImpl' in the generic type or method 'UserQuery.IResolver.GetResolver()'. There is no implicit reference conversion from 'UserQuery.ParseAnalytic' to 'UserQuery.IAnalytic'.
Avoiding me to make stupid mistakes.
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53280136%2fproblems-with-c-sharp-type-inference-mechanism-for-extension-methods%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
Not sure this is exactly what you are looking for but here's how you only need to specify the type of the resolver during instantiation or in an implementation (you can't avoid specification/casts altogether):
public interface IAnalytic { }
public interface IAnalytic<TInput, TOutput> : IAnalytic
{
TOutput Calculate(TInput input);
}
public interface IAnalyticResolver<T, TOutput> where T : IAnalytic
{
TOutput Evaluate();
}
public interface IResolver<TOutput>
{
IAnalyticResolver<TAnalyticImpl, TOutput> GetResolver<TAnalyticImpl>() where TAnalyticImpl : IAnalytic;
}
public class ParseAnalytic : IAnalytic<string, int>
{
public int Calculate(string input) => int.Parse(input);
}
public class IntResolver : IResolver<int>
{
public IAnalyticResolver<TAnalyticImpl, int> GetResolver<TAnalyticImpl>() where TAnalyticImpl : IAnalytic
{
throw new NotImplementedException();
}
}
class Program
{
static void Main(string args)
{
IResolver<int> r = new IntResolver();
int result = r.GetResolver<ParseAnalytic>().Evaluate();
}
}
Thanks, that helps, however I was wanted to leave the inference of the Output type to the call. because I wanted to have many calls tor.GetResolver<...>.Evaluate()
each returning the correct type.
– Fabio Marreco
Nov 13 '18 at 16:09
Yeah I see. I think the issue is that you don't know them because you can't tell if you are dealing with IAnalytic or IAnalytic<TInput, TOutput>. When I remove IAnalytic it does work but then you have to specify all the types everywhere. Maybe it would help if you gave me some implementations of it all for a specific use case. Could you share one?
– fstam
Nov 13 '18 at 17:42
add a comment |
Not sure this is exactly what you are looking for but here's how you only need to specify the type of the resolver during instantiation or in an implementation (you can't avoid specification/casts altogether):
public interface IAnalytic { }
public interface IAnalytic<TInput, TOutput> : IAnalytic
{
TOutput Calculate(TInput input);
}
public interface IAnalyticResolver<T, TOutput> where T : IAnalytic
{
TOutput Evaluate();
}
public interface IResolver<TOutput>
{
IAnalyticResolver<TAnalyticImpl, TOutput> GetResolver<TAnalyticImpl>() where TAnalyticImpl : IAnalytic;
}
public class ParseAnalytic : IAnalytic<string, int>
{
public int Calculate(string input) => int.Parse(input);
}
public class IntResolver : IResolver<int>
{
public IAnalyticResolver<TAnalyticImpl, int> GetResolver<TAnalyticImpl>() where TAnalyticImpl : IAnalytic
{
throw new NotImplementedException();
}
}
class Program
{
static void Main(string args)
{
IResolver<int> r = new IntResolver();
int result = r.GetResolver<ParseAnalytic>().Evaluate();
}
}
Thanks, that helps, however I was wanted to leave the inference of the Output type to the call. because I wanted to have many calls tor.GetResolver<...>.Evaluate()
each returning the correct type.
– Fabio Marreco
Nov 13 '18 at 16:09
Yeah I see. I think the issue is that you don't know them because you can't tell if you are dealing with IAnalytic or IAnalytic<TInput, TOutput>. When I remove IAnalytic it does work but then you have to specify all the types everywhere. Maybe it would help if you gave me some implementations of it all for a specific use case. Could you share one?
– fstam
Nov 13 '18 at 17:42
add a comment |
Not sure this is exactly what you are looking for but here's how you only need to specify the type of the resolver during instantiation or in an implementation (you can't avoid specification/casts altogether):
public interface IAnalytic { }
public interface IAnalytic<TInput, TOutput> : IAnalytic
{
TOutput Calculate(TInput input);
}
public interface IAnalyticResolver<T, TOutput> where T : IAnalytic
{
TOutput Evaluate();
}
public interface IResolver<TOutput>
{
IAnalyticResolver<TAnalyticImpl, TOutput> GetResolver<TAnalyticImpl>() where TAnalyticImpl : IAnalytic;
}
public class ParseAnalytic : IAnalytic<string, int>
{
public int Calculate(string input) => int.Parse(input);
}
public class IntResolver : IResolver<int>
{
public IAnalyticResolver<TAnalyticImpl, int> GetResolver<TAnalyticImpl>() where TAnalyticImpl : IAnalytic
{
throw new NotImplementedException();
}
}
class Program
{
static void Main(string args)
{
IResolver<int> r = new IntResolver();
int result = r.GetResolver<ParseAnalytic>().Evaluate();
}
}
Not sure this is exactly what you are looking for but here's how you only need to specify the type of the resolver during instantiation or in an implementation (you can't avoid specification/casts altogether):
public interface IAnalytic { }
public interface IAnalytic<TInput, TOutput> : IAnalytic
{
TOutput Calculate(TInput input);
}
public interface IAnalyticResolver<T, TOutput> where T : IAnalytic
{
TOutput Evaluate();
}
public interface IResolver<TOutput>
{
IAnalyticResolver<TAnalyticImpl, TOutput> GetResolver<TAnalyticImpl>() where TAnalyticImpl : IAnalytic;
}
public class ParseAnalytic : IAnalytic<string, int>
{
public int Calculate(string input) => int.Parse(input);
}
public class IntResolver : IResolver<int>
{
public IAnalyticResolver<TAnalyticImpl, int> GetResolver<TAnalyticImpl>() where TAnalyticImpl : IAnalytic
{
throw new NotImplementedException();
}
}
class Program
{
static void Main(string args)
{
IResolver<int> r = new IntResolver();
int result = r.GetResolver<ParseAnalytic>().Evaluate();
}
}
answered Nov 13 '18 at 13:11
fstamfstam
366213
366213
Thanks, that helps, however I was wanted to leave the inference of the Output type to the call. because I wanted to have many calls tor.GetResolver<...>.Evaluate()
each returning the correct type.
– Fabio Marreco
Nov 13 '18 at 16:09
Yeah I see. I think the issue is that you don't know them because you can't tell if you are dealing with IAnalytic or IAnalytic<TInput, TOutput>. When I remove IAnalytic it does work but then you have to specify all the types everywhere. Maybe it would help if you gave me some implementations of it all for a specific use case. Could you share one?
– fstam
Nov 13 '18 at 17:42
add a comment |
Thanks, that helps, however I was wanted to leave the inference of the Output type to the call. because I wanted to have many calls tor.GetResolver<...>.Evaluate()
each returning the correct type.
– Fabio Marreco
Nov 13 '18 at 16:09
Yeah I see. I think the issue is that you don't know them because you can't tell if you are dealing with IAnalytic or IAnalytic<TInput, TOutput>. When I remove IAnalytic it does work but then you have to specify all the types everywhere. Maybe it would help if you gave me some implementations of it all for a specific use case. Could you share one?
– fstam
Nov 13 '18 at 17:42
Thanks, that helps, however I was wanted to leave the inference of the Output type to the call. because I wanted to have many calls to
r.GetResolver<...>.Evaluate()
each returning the correct type.– Fabio Marreco
Nov 13 '18 at 16:09
Thanks, that helps, however I was wanted to leave the inference of the Output type to the call. because I wanted to have many calls to
r.GetResolver<...>.Evaluate()
each returning the correct type.– Fabio Marreco
Nov 13 '18 at 16:09
Yeah I see. I think the issue is that you don't know them because you can't tell if you are dealing with IAnalytic or IAnalytic<TInput, TOutput>. When I remove IAnalytic it does work but then you have to specify all the types everywhere. Maybe it would help if you gave me some implementations of it all for a specific use case. Could you share one?
– fstam
Nov 13 '18 at 17:42
Yeah I see. I think the issue is that you don't know them because you can't tell if you are dealing with IAnalytic or IAnalytic<TInput, TOutput>. When I remove IAnalytic it does work but then you have to specify all the types everywhere. Maybe it would help if you gave me some implementations of it all for a specific use case. Could you share one?
– fstam
Nov 13 '18 at 17:42
add a comment |
Thanks everyone,
But I ended up creating a intermediary interface such as
public interface IAnalytic<TOutput> : IAnalytic { }
and making IAnalytic<,>
inherit from it:
public interface IAnalytic<TInput, TOutput> : IAnalytic<TOutput>
{
TOutput Calculate(TInput input);
}
And also changed the IAnalyticResolverInterface
to work with it:
public interface IAnalyticResolver<TAnalytic, TOutput> where TAnalytic : IAnalytic<TOutput>
{
TOutput Evaluate();
}
public interface IResolver
{
IAnalyticResolver<TAnalyticImpl, TOutput> GetResolver<TAnalyticImpl, TOutput> ()
where TAnalyticImpl : IAnalytic<TOutput>;
}
with this, I can call the resolver returning the correct type. However, I have to explicitly state the TOutput
type.
int i = r.GetResolver<ParseAnalytic, int>().Evaluate();
this is redundant, since ParseAnalytic
already is a IAnalytic<string, int>
. But I can cope with that because at least int
is the only acceptable type in this situation. If I try to write something like
double i = r.GetResolver<ParseAnalytic, double>().Evaluate();
the compiler will say:
CS0311 The type 'UserQuery.ParseAnalytic' cannot be used as type parameter 'TAnalyticImpl' in the generic type or method 'UserQuery.IResolver.GetResolver()'. There is no implicit reference conversion from 'UserQuery.ParseAnalytic' to 'UserQuery.IAnalytic'.
Avoiding me to make stupid mistakes.
add a comment |
Thanks everyone,
But I ended up creating a intermediary interface such as
public interface IAnalytic<TOutput> : IAnalytic { }
and making IAnalytic<,>
inherit from it:
public interface IAnalytic<TInput, TOutput> : IAnalytic<TOutput>
{
TOutput Calculate(TInput input);
}
And also changed the IAnalyticResolverInterface
to work with it:
public interface IAnalyticResolver<TAnalytic, TOutput> where TAnalytic : IAnalytic<TOutput>
{
TOutput Evaluate();
}
public interface IResolver
{
IAnalyticResolver<TAnalyticImpl, TOutput> GetResolver<TAnalyticImpl, TOutput> ()
where TAnalyticImpl : IAnalytic<TOutput>;
}
with this, I can call the resolver returning the correct type. However, I have to explicitly state the TOutput
type.
int i = r.GetResolver<ParseAnalytic, int>().Evaluate();
this is redundant, since ParseAnalytic
already is a IAnalytic<string, int>
. But I can cope with that because at least int
is the only acceptable type in this situation. If I try to write something like
double i = r.GetResolver<ParseAnalytic, double>().Evaluate();
the compiler will say:
CS0311 The type 'UserQuery.ParseAnalytic' cannot be used as type parameter 'TAnalyticImpl' in the generic type or method 'UserQuery.IResolver.GetResolver()'. There is no implicit reference conversion from 'UserQuery.ParseAnalytic' to 'UserQuery.IAnalytic'.
Avoiding me to make stupid mistakes.
add a comment |
Thanks everyone,
But I ended up creating a intermediary interface such as
public interface IAnalytic<TOutput> : IAnalytic { }
and making IAnalytic<,>
inherit from it:
public interface IAnalytic<TInput, TOutput> : IAnalytic<TOutput>
{
TOutput Calculate(TInput input);
}
And also changed the IAnalyticResolverInterface
to work with it:
public interface IAnalyticResolver<TAnalytic, TOutput> where TAnalytic : IAnalytic<TOutput>
{
TOutput Evaluate();
}
public interface IResolver
{
IAnalyticResolver<TAnalyticImpl, TOutput> GetResolver<TAnalyticImpl, TOutput> ()
where TAnalyticImpl : IAnalytic<TOutput>;
}
with this, I can call the resolver returning the correct type. However, I have to explicitly state the TOutput
type.
int i = r.GetResolver<ParseAnalytic, int>().Evaluate();
this is redundant, since ParseAnalytic
already is a IAnalytic<string, int>
. But I can cope with that because at least int
is the only acceptable type in this situation. If I try to write something like
double i = r.GetResolver<ParseAnalytic, double>().Evaluate();
the compiler will say:
CS0311 The type 'UserQuery.ParseAnalytic' cannot be used as type parameter 'TAnalyticImpl' in the generic type or method 'UserQuery.IResolver.GetResolver()'. There is no implicit reference conversion from 'UserQuery.ParseAnalytic' to 'UserQuery.IAnalytic'.
Avoiding me to make stupid mistakes.
Thanks everyone,
But I ended up creating a intermediary interface such as
public interface IAnalytic<TOutput> : IAnalytic { }
and making IAnalytic<,>
inherit from it:
public interface IAnalytic<TInput, TOutput> : IAnalytic<TOutput>
{
TOutput Calculate(TInput input);
}
And also changed the IAnalyticResolverInterface
to work with it:
public interface IAnalyticResolver<TAnalytic, TOutput> where TAnalytic : IAnalytic<TOutput>
{
TOutput Evaluate();
}
public interface IResolver
{
IAnalyticResolver<TAnalyticImpl, TOutput> GetResolver<TAnalyticImpl, TOutput> ()
where TAnalyticImpl : IAnalytic<TOutput>;
}
with this, I can call the resolver returning the correct type. However, I have to explicitly state the TOutput
type.
int i = r.GetResolver<ParseAnalytic, int>().Evaluate();
this is redundant, since ParseAnalytic
already is a IAnalytic<string, int>
. But I can cope with that because at least int
is the only acceptable type in this situation. If I try to write something like
double i = r.GetResolver<ParseAnalytic, double>().Evaluate();
the compiler will say:
CS0311 The type 'UserQuery.ParseAnalytic' cannot be used as type parameter 'TAnalyticImpl' in the generic type or method 'UserQuery.IResolver.GetResolver()'. There is no implicit reference conversion from 'UserQuery.ParseAnalytic' to 'UserQuery.IAnalytic'.
Avoiding me to make stupid mistakes.
answered Nov 22 '18 at 11:49
Fabio MarrecoFabio Marreco
1,1361314
1,1361314
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53280136%2fproblems-with-c-sharp-type-inference-mechanism-for-extension-methods%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown