Problems with C# type inference mechanism for extension methods












0















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)










share|improve this question





























    0















    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)










    share|improve this question



























      0












      0








      0


      0






      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)










      share|improve this question
















      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#






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      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
























          2 Answers
          2






          active

          oldest

          votes


















          0














          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();
          }
          }





          share|improve this answer
























          • 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



















          0














          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.






          share|improve this answer























            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
            });


            }
            });














            draft saved

            draft discarded


















            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









            0














            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();
            }
            }





            share|improve this answer
























            • 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
















            0














            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();
            }
            }





            share|improve this answer
























            • 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














            0












            0








            0







            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();
            }
            }





            share|improve this answer













            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();
            }
            }






            share|improve this answer












            share|improve this answer



            share|improve this answer










            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 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



















            • 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

















            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













            0














            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.






            share|improve this answer




























              0














              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.






              share|improve this answer


























                0












                0








                0







                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.






                share|improve this answer













                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.







                share|improve this answer












                share|improve this answer



                share|improve this answer










                answered Nov 22 '18 at 11:49









                Fabio MarrecoFabio Marreco

                1,1361314




                1,1361314






























                    draft saved

                    draft discarded




















































                    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.




                    draft saved


                    draft discarded














                    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





















































                    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







                    Popular posts from this blog

                    Bressuire

                    Vorschmack

                    Quarantine