High-order Function question...

sipi41

Member
Joined
Apr 12, 2020
Messages
6
Programming Experience
1-3
Hello, I'm newbie to c#, and I was reading on my book that I can pass functions as parameters and receive functions or both... so I'm trying to make an exercise but can't make this work... please help!

My idea is to create a static function like this:
C#:
public static void TestMethod<T1, TResult>(Func<T1, TResult> myfunction ) {
            ...
}
Now, the idea is that I can call this static method by providing a function that matches the T1 and the TResult like this:
C#:
Func<string, string> ChangeName = name => $"My name is: {name}";

TestMethod<string, string>(ChangeName);
Now my understanding is that inside the TestMethod I received a function, now I can make use of the myfunction and call it to action, am I right? in this case, if I call the function it should return an string (according to my definition), so I think I should be able to do this:
C#:
public static void TestMethod<T1, TResult>(Func<T1, TResult> myfunction ) {
    Console.WriteLine(    myfunction.Invoke()        );
        // or
    Console.WriteLine(    myfunction()    );
}
But I can't because it display an error asking for a T1 parameter...
Untitled.png


PLEASE HELP!...
 
You are specifying that your function has a parameter. Where is the argument for that parameter? You specifically state here:
C#:
Func<string, string> ChangeName = name => $"My name is: {name}";
That your function is supposed to accept a name value and return some text containing that name. When you call it, where's the name? You're not providing it. It has to come from somewhere and you have to pass it in to that function.
 
You are specifying that your function has a parameter. Where is the argument for that parameter? You specifically state here:
C#:
Func<string, string> ChangeName = name => $"My name is: {name}";
That your function is supposed to accept a name value and return some text containing that name. When you call it, where's the name? You're not providing it. It has to come from somewhere and you have to pass it in to that function.
What would be the right implementation then? for example, if on my function I do a call to a database or a text file to get the name, now I have a variable with a name inside the method, now I'm ready to call the function, how do I do that then?? thank you for your help! :)
 
Here's a freebie:
C#:
Console.WriteLine(myfunction("Asmodeus"));
 
Here's a freebie:
C#:
Console.WriteLine(myfunction("Asmodeus"));
Can't do this... this is why this is making me crazy... my understanding is that I require a string but the system is asking for a T1 type, not a string, so an error appears saying "Cant convert string to T1"...
 
Ah! Good point... Currently busy right now, but here's a quick and dirty workaround:
C#:
class Program
{
    public static void TestMethod<T1, TResult>(Func<T1, TResult> myfunction, T1 param1)
    {
        Console.WriteLine(myfunction(param1));
    }

    static void Main()
    {
        Func<string, string> changeName = name => $"My name is: {name}";

        TestMethod<string, string>(changeName, "Asmodeus");
    }
}
 
If you are going to write a generic method then you have to write code that is generic, i.e. will work for all generic parameter types. Basically, what you're trying to do doesn;t really make sense. You're trying to contrive something to demonstrate specific functionality and it doesn;t make sense. This is why so many beginner assignments are garbage: because they try to use functionality is stupid ways that no sensible developer would ever use it in.

In your case, your TestMethod says that it will accept any method with a single parameter and a return type and execute it. How do you expect to execute a method with a parameter of type T1 if you have no value of that type to pass as an argument? TestMethod has to get a value of type T1 from somewhere. @Skydiver has shown one way to accomplish that, i.e. to add a parameter of that type to TestMethod. That pretty much renders TestMethod pointless, except as a learning aid. The problem is that, in trying to learn something, you have made it more confusing. Such is life though. Sometimes, it's the only way.
 
If you are going to write a generic method then you have to write code that is generic, i.e. will work for all generic parameter types. Basically, what you're trying to do doesn;t really make sense. You're trying to contrive something to demonstrate specific functionality and it doesn;t make sense. This is why so many beginner assignments are garbage: because they try to use functionality is stupid ways that no sensible developer would ever use it in.

In your case, your TestMethod says that it will accept any method with a single parameter and a return type and execute it. How do you expect to execute a method with a parameter of type T1 if you have no value of that type to pass as an argument? TestMethod has to get a value of type T1 from somewhere. @Skydiver has shown one way to accomplish that, i.e. to add a parameter of that type to TestMethod. That pretty much renders TestMethod pointless, except as a learning aid. The problem is that, in trying to learn something, you have made it more confusing. Such is life though. Sometimes, it's the only way.
ok... this comment did not help much... we already know we need a T1 type value from somewhere... if this is so wrong, what's your solution? if this is pointless, what could be better then? Thanks for your help on clarifying this...
 
As I said, the issue is that you are trying to contrive something. If you had an idea where you might actually do something like this then getting the required data in would not be an issue. A far more realistic scenario is that you have a method with no parameters and it gets the data it needs internally by whatever mechanism is appropriate. E.g.
C#:
using System;
using System.IO;

namespace ConsoleApp2
{
    class Program
    {
        static void Main(string[] args)
        {
            // Use a method group as a delegate.
            DisplayOutput(Console.ReadLine);

            // Use a Lambda as a delegate.
            DisplayOutput(() =>
            {
                Console.Write("Enter text file path: ");

                var filePath = Console.ReadLine();

                return File.Exists(filePath)
                    ? "No file specified"
                    : File.ReadAllText(filePath);
            });

            Console.ReadLine();
        }

        private static void DisplayOutput<TResult>(Func<TResult> method)
        {
            Console.WriteLine(method());
        }
    }
}
You can then use DisplayOutput to execute any parameterless function and output the result to the console.
 
As I said, the issue is that you are trying to contrive something. If you had an idea where you might actually do something like this then getting the required data in would not be an issue. A far more realistic scenario is that you have a method with no parameters and it gets the data it needs internally by whatever mechanism is appropriate. E.g.
C#:
using System;
using System.IO;

namespace ConsoleApp2
{
    class Program
    {
        static void Main(string[] args)
        {
            // Use a method group as a delegate.
            DisplayOutput(Console.ReadLine);

            // Use a Lambda as a delegate.
            DisplayOutput(() =>
            {
                Console.Write("Enter text file path: ");

                var filePath = Console.ReadLine();

                return File.Exists(filePath)
                    ? "No file specified"
                    : File.ReadAllText(filePath);
            });

            Console.ReadLine();
        }

        private static void DisplayOutput<TResult>(Func<TResult> method)
        {
            Console.WriteLine(method());
        }
    }
}
You can then use DisplayOutput to execute any parameterless function and output the result to the console.
makes sense... we do our login inside the DisplayOutput... then if wherever is true or X we call the method, no parameters...
 
Back
Top Bottom