Jump to content

  • Log In with Google      Sign In   
  • Create Account

Generic C# delegates


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
15 replies to this topic

#1 satsujin   Members   -  Reputation: 139

Like
1Likes
Like

Posted 18 November 2013 - 08:14 AM

I have recently learned about delegates in C#. They are typesafe but I am wondering if you can create a delegate in some form that can point to functions with different return types and parameters. I think my solution may lie somewhere with Func, <T> or object type definition for the delegate. However if I use object type for delegate, the function can also only return an object and to find out what value was returned I'll have to make something that uses the is keyword to return a string representation of the value, won't I?

 

I am not too sure how to use Func or <T> when creating the delegate instance for different functions so can someone please help me?



Sponsor:

#2 ApochPiQ   Moderators   -  Reputation: 15699

Like
2Likes
Like

Posted 18 November 2013 - 08:47 AM

It's pretty easy:

public delegate void DoSomething<T> (T whatever);

public static void Implementation(int whatever);


// And then:
DoSomething<int> myDelegate = Implementation;

Note that DoSomething<int> is a distinct type from DoSomething<string> and so on, so you can't directly create, say, a list of delegates that are generic in this manner. It's still possible, it just takes some wrapper code.

#3 satsujin   Members   -  Reputation: 139

Like
0Likes
Like

Posted 18 November 2013 - 09:31 AM

Could you give me some clue about the wrapper code? Would it be something using reflection to find out the return type of the function, its methodname, and parameters?

 

Also in the code above the delegate only accepts functions that return void right? would public delegate T DoSomething<T>(T whatever) be more generic?


Edited by satsujin, 18 November 2013 - 09:37 AM.


#4 Eck   Members   -  Reputation: 2770

Like
3Likes
Like

Posted 18 November 2013 - 09:47 AM

I am wondering if you can create a delegate in some form that can point to functions with different return types and parameters.
 

I'm not 100% sure what you're asking. Can you give me a concrete example of what you're trying to do? I whipped up a sample, but I'm not sure it's what you're looking for.

using System;
using System.Collections.Generic;
 
 
namespace GameDevExample
{
 
    // We have a generic class here. Picture Generics as using variables for your Types.
    public class GenericExample<GenericOperandType, GenericReturnType>
    {
        // Constructor makes sure we have a ListOfStuff initialized to hold our list of stuff
        public GenericExample()
        {
            ListOfStuff = new List<GenericOperandType>();
        }
 
        // We'll have a generic list of stuff.
        public List<GenericOperandType> ListOfStuff { get; set; }
 
        // Our DoSomeStuff delegate serves as our function signature.
        public delegate GenericReturnType DoSomeStuffDelegate(GenericOperandType firstItemInList, GenericOperandType lastItemInList);
 
        public GenericReturnType ReturnedFromYourDelegate { get; set; }
 
        // Here we take our delegate as a parameter so our generic class can call it. It's not sure what your delegate does, it just knows the parameters and return type.
        public GenericReturnType DoSomeStuff(DoSomeStuffDelegate doSomeStuffDelegate)
        {
            if (ListOfStuff.Count == 0)
                throw new InvalidOperationException("Sorry, can't do stuff on an empty list.");
            else
                ReturnedFromYourDelegate = doSomeStuffDelegate(ListOfStuff[0], ListOfStuff[ListOfStuff.Count - 1]);
 
            return ReturnedFromYourDelegate;
        }
    }
 
    class Program
    {
        static void Main(string[] args)
        {
            GenericExample<int, int> genericExampleIntInt = new GenericExample<int, int>();
            genericExampleIntInt.ListOfStuff.Add(1);
            genericExampleIntInt.ListOfStuff.Add(2);
            genericExampleIntInt.ListOfStuff.Add(3);
            Console.WriteLine(string.Format("genericExampleIntInt - DoSomeStuff returns: {0}", genericExampleIntInt.DoSomeStuff(DoSomeStuffInt)));
 
            GenericExample<string, int> genericExampleStringInt = new GenericExample<string, int>();
            genericExampleStringInt.ListOfStuff.Add("potato");
            genericExampleStringInt.ListOfStuff.Add("2*pi*r^2");
            genericExampleStringInt.ListOfStuff.Add("nonsense");
            Console.WriteLine(string.Format("genericExampleStringInt - DoSomeStuff returns: {0}", genericExampleStringInt.DoSomeStuff(DoSomeStuffStringInt)));
 
            GenericExample<int, string> genericExampleIntString = new GenericExample<int, string>();
            genericExampleIntString.ListOfStuff.Add(73);
            genericExampleIntString.ListOfStuff.Add(-273);
            genericExampleIntString.ListOfStuff.Add(314);
            Console.WriteLine(string.Format("genericExampleIntString - DoSomeStuff returns: {0}", genericExampleIntString.DoSomeStuff(DoSomeStuffIntString)));
 
            Console.WriteLine();
            Console.WriteLine("Press enter to exit.");
            Console.ReadLine();
        }
 
        // These are static because Main is a static function.
        // Returns the first value
        public static int DoSomeStuffInt(int firstInList, int lastInList)
        {
            return firstInList;
        }
 
        // Returns the sum of the lengths of the strings.
        public static int DoSomeStuffStringInt(string firstInList, string lastInList)
        {
            return firstInList.Length + lastInList.Length;
        }
 
        // Returns a string of the difference of the two arguments.
        public static string DoSomeStuffIntString(int firstInList, int lastInList)
        {
            return firstInList.ToString() + " - " + lastInList.ToString() + " = " + (firstInList - lastInList).ToString();
        }
    }
}

Edited by Eck, 18 November 2013 - 09:51 AM.


#5 ApochPiQ   Moderators   -  Reputation: 15699

Like
1Likes
Like

Posted 18 November 2013 - 09:57 AM

Generic delegates do not "exist" as their own types. You can think of them as mad-libs. They don't really do anything until you fill in the blanks, at which point each combination of generic parameters creates a new, distinct type.
 
So a delegate that takes a Foo and returns a Bar will always be a different type (and not convertible to) a delegate that takes a Baz and returns a Quux.


If you absolutely want to be generic over return type, you have a lot of work ahead of you, and there are a lot of caveats. But I suspect this isn't actually the solution to your problem. What exactly are you trying to accomplish?

#6 satsujin   Members   -  Reputation: 139

Like
0Likes
Like

Posted 18 November 2013 - 10:14 AM

I'm still pretty new to generics and delegates so I just wanted to find out how flexible a delegate instance could be in what it pointed to. I don't have any specific application goal in mind.

 

Eck's class may be what I'm looking for but since I'm new to this I'll need to scrutinize it more closely. Thanks for your submission Eck.



#7 satsujin   Members   -  Reputation: 139

Like
0Likes
Like

Posted 18 November 2013 - 10:22 AM

Eck, can void be used as a type when creating an instance of genericExample? Also, the function your delegate points to must always have the same two variables in the list regardless of the type right? Would a better option be to pass in a list of <object> types to the delegate function? So that parameters can be added to the list before calling to the function and pulled out in order from inside the function?


Edited by satsujin, 18 November 2013 - 11:17 AM.


#8 Eck   Members   -  Reputation: 2770

Like
0Likes
Like

Posted 18 November 2013 - 10:58 AM

Thanks for your submission Eck.

Thanks are cheap! I work for vote ups! Now click that green up arrow for me. :D

 

.Net doesn't support void as a generic type, so no you couldn't have something like: GenericExample<int, void>.

 

Generics are a pretty powerful concept. Early in your career, you probably won't use them much (other than making hefty use of the generic collections available like List, Dictionary, etc.). If you find yourself copying and pasting a function and all you're doing is changing the type, a Generic might be what you're looking for. But a function that takes an interface might do just as well. I like ApochPiQ's mad-lib analogy. 

 

Delegates are also a powerful concept. It gives the user of your class more say in what's going on. I've used delegates in a credit card processing module for PersistAboutToSend, and PersistRawResponse functions.  My credit card processor knew all about sending/receiving communications  and what to do in error states, but it didn't know about how those responses should be stored. Before it started talking, and after it heard back from the credit card processor, it called those delegates. In this case, the caller persisted them to the database, but he could just have easily stored it into a file, kept it in memory, or thrown it away completely and my processor wouldn't be the wiser. Look up dependency injection or inversion of control.

 

Generics combined with delegates can do some funky stuff. :)

 

If someone can come up with an example for when Generic delegates might be handy it will be much easier to understand. All of the ideas I'm having are silly. My creativity module is still coming online because I stayed up late last night.

 

- Eck



#9 Eck   Members   -  Reputation: 2770

Like
1Likes
Like

Posted 18 November 2013 - 11:36 AM

Also, the function your delegate points to must always have the same two variables in the list regardless of the type right?

Yes, once you specify the type, it's set in stone. But you can also use inheritance with Generics so if you had a list of IGameObjects which contained IShips, IBullets, and IAsteroids, you could treat everything like IGameObjects and do work on them. Much like you were wanting to do with your specifying the object type.

 

Would a better option be to pass in a list of <object> types to the delegate function? So that parameters can be added to the list before calling to the function and pulled out in order from inside the function?

It would be better depending on what you're trying to do. We're still in contrived-silly-example land right now. Get that concrete example of what you want, and we can explore the concept more deeply. It might turn out that this isn't what you want at all. smile.png

 

If this is just for "what-if's", I still think a real (or real-ish) problem to solve will help us.

 

- Eck


Edited by Eck, 18 November 2013 - 11:36 AM.


#10 satsujin   Members   -  Reputation: 139

Like
0Likes
Like

Posted 18 November 2013 - 12:39 PM

Well, what got me into looking at this was that I was working on a point and click adventure game in XNA and wanted to define a script with various functions that linked to a LookAt() delegate. So the script would be called by the interface and which function LookAt() pointed to would be decided by state variables in the script. Later I realized all the functions would be type void so there was no need for Generics in the return type but maybe the different functions could have varying types in the parameter list.

I am still not sure how to link to the program from the script. Probably the best method would be to have LookAt() as a function that loads different scripts for each function but that can get messy and I would have to hardcode the logic for selecting scripts based on state variables into the C# program. Can C# be used for scripting? I've heard good things about Lua but the documentation for it in C# is very limited online.


Edited by satsujin, 18 November 2013 - 12:42 PM.


#11 ApochPiQ   Moderators   -  Reputation: 15699

Like
0Likes
Like

Posted 18 November 2013 - 12:50 PM

I don't really follow your design here. What does LookAt() do? What does it operate on? What kinds of parameters would it take?



#12 satsujin   Members   -  Reputation: 139

Like
1Likes
Like

Posted 19 November 2013 - 12:37 AM

LookAt() at would be a method in a GameEntity class.

 

It runs a script that would change elements int the current room scene like putting up descriptive text, moving/creating other animations or changing state variables.

 

It is activated when the player clicks on a GameEntity object with the look cursor active.

 

It wouldnt take a generic number or type of parameters but the script that it calls may take state variables defined in a StateManager in the game. I supposed I could just pass in the StateManager in the game to the script and let it pick from there but that might contain a large number of unneeded state info.

 

My main goal for this was scripting the logic for my game so I wouldnt have to hardcode it. So far I only have a ScreenManager that Draws,Updates, Adds, Removes screens, an Input Manager that checks for a Click instead of a MouseDown and a Texture class that can Move the texture as well as check if the method has been clicked(either within the Bounds of the Texture Rectangle or on a non-transparent pixel of the texture). Scripting is my main goal but the info I have found on the net has been lacking. I would like to know if it would be possible for a one-man team to make a SCUMM like adventure game.



#13 Eck   Members   -  Reputation: 2770

Like
1Likes
Like

Posted 19 November 2013 - 10:18 AM

Sorry I dropped off yesterday. Work and all that. :P

 

So, a concrete example. You'd like to write scripts to access and modify game states and game entities. Let's say we want this. A numpad console beside a locked door with some paper taped next to it. By default when you look at it, the writing says: "The pass code is...." But if you're wearing the coke-bottle glasses you assembled earlier, looking at it will display some different text. It tells you the .'s are the numbers 1 2 3 4.

 

I really started going crazy with this and the post was getting away from me. I had to start overFun problem to solve! :)

 

Let's say we already have our GameWorld loaded, we have a Room or a Scene object, Game Entities know how to draw themselves. etc. You've decided on Lua for your game scripts. That's a decent choice because after your game gains popularity you'll be rolling in the dough from all the community created mods driving up the sales of your engine. We can dream can't we? :)

 

So you've got your input manager wired up. You've selected look at, and somehow identified that we've clicked the PassCodeText GameEntity. I'm picturing the World creation loaded up all the Rooms/Scenes/GameEntities with all the knowledge they'd need. So there'd be some script equivalent for LookAt defined in your world data files.

 

// This code would be associated with the PassCodeText game entity.
// I'm writing in C# because I don't know Lua yet.
if(verb == "LookAt")
{
    if(StateManager.HasState("COKE_BOTTLE_GLASSES_EQUIPPED"))
        GameEngine.DisplayText("Oh, those .'s are actually the numbers 1-2-3-4");
    else
        GameEngine.DisplayText("The pass code is ....");
 
    // In actuality your script might look like this. Your script writers don't need to know the guts of your program.
    if(HasState("COKE_BOTTLE_GLASSES_EQUIPPED")) // HasState would somehow be interpreted as "Use the state manager to check for the state "blah"
        DisplayText("Oh, those .'s are actually the numbers 1-2-3-4");
    else
        DisplayText("The pass code is ....");
 
}

 

Side note, this could just as easily be mocked up in XML data files rather than scripts. 

 

You basically need to figure out what you want to be able to drive via scripts and come up with an interface for your game's soft-code. So after your input manager knows you've clicked the PassCodeText entity with the LookAt verb, it triggers the associated script.

  • In C#, your GameEntity class would have a LookAt() function. (or a DoVerb function with the verb as a parameter).
  • It probably needs to take your StateManager and your GameEngine classes as parameters as well
  • When its interpreting the GameEntity's script, you'll be mapping from the script construct over into your code. 

I don't think you'll need delegates or generics here at all. :) You're world loading will have associated the script to your PassCodeText GameEntity. When you're interpreting your Lua scripts, you'll be mapping them to calls into your StateManager and GameEngine code. It's pretty much a data driven game at that point.

 

I wouldn't be concerned about passing the huge "state manager" class around. It's a class and thus - a reference type. Passing it around won't be slow because you're not copying the data every time. You're passing a reference to it.

 

Yes, I think a SCUMM adventure game is doable for a one-man team. You'll need the following skills: art, sound, creative writing, sense of humor, puzzle creation, and standard game dev stuff.

 

This article might get you going too:

http://www.gamedev.net/page/resources/_/technical/game-programming/using-lua-with-c-r2275

 

- Eck



#14 satsujin   Members   -  Reputation: 139

Like
1Likes
Like

Posted 19 November 2013 - 08:53 PM

Glad to see you back Eck. I upvoted your last post. So, how familiar are you with Lua? I was wondering if you knew where I could access info about the LuaInterface C# API. The amount of stuff stuff I've searched on Google only point to C++/C API info or contains info about the scripting language alone, not about how to interface between C# and Lua. I know how to register a C# function so it's accessible on lua but am looking how to register a lua function with c# and also to load classes instances and references from C#.

 

I'd want to use my game engine as minimally as possible : say just for handling graphics, sound, input, object creation and similar basics and run scripts to handle the rest. May not be easy to debug but would make a good flexible engine model. To do this, wouldn't I have to create a wrapper model to run concurrent lua scripts along with XNA's Update and Draw loops? Maybe something that stores a list of currently running scripts and executes one line on each one, return control to XNA loops and then executes the next lines? Then clear those scripts when a new screen is loaded and load a new bunch of scripts?

 

By the way, there is no professional goal with the project. This is purely a hobby enterprise where I am just curious about how this stuff works and am hoping for a learning experience.


Edited by satsujin, 19 November 2013 - 08:55 PM.


#15 Eck   Members   -  Reputation: 2770

Like
0Likes
Like

Posted 20 November 2013 - 09:04 AM

So, how familiar are you with Lua?

Honestly not much. I'll be learning it soon and I've been using your questions as an excuse to start some research. :)

 

The article I linked earlier has some neat stuff: 

http://www.gamedev.net/page/resources/_/technical/game-programming/using-lua-with-c-r2275

 

After doing some searches, it looks like there's a LuaInterface C# wrapper library. I found this post when I googled: C# LuaInterface documentation

http://stackoverflow.com/questions/1339917/luainterface-docs

 

Specifically, the guide.pdf link has a section on calling lua from C# and C# from lua:

https://bitbucket.org/maxint/luainterface/src/7b4bd173ecfd/luainterface/doc/guide.pdf

 

To do this, wouldn't I have to create a wrapper model to run concurrent lua scripts along with XNA's Update and Draw loops? Maybe something that stores a list of currently running scripts and executes one line on each one, return control to XNA loops and then executes the next lines? Then clear those scripts when a new screen is loaded and load a new bunch of scripts?

There are a million ways to skin this cat. I wasn't picturing multiple concurrent scripts running in my "design" (my shoot from the hip initial thoughts). I was thinking the world loading would build your level. Each room would know what game entities it had, and each game entity would know which verbs it could handle, and each verb would be tied to lua scripts that would interface with your game engine:

  • checking and setting states - In the example above, reading the note with the coke bottle glasses equipped could set a KnowsSecretLabPassCode state, and the keypad could check that state in it's "use" script
  • creating/destroying objects - Once you have the wire, and two coke bottles, you could use the "combine" verb to create the coke bottle glasses game entity, destroying the wire and coke bottles in the process
  • special states tied to graphics - SecretLabDoor - open vs closed, player wearing coke bottle glasses
  • trigger an animation/cut scene

But these are just my initial thoughts. I haven't done any deep thinking about this.

 

By the way, there is no professional goal with the project. This is purely a hobby enterprise where I am just curious about how this stuff works and am hoping for a learning experience.

Cool. It's pretty much the same for me. You had some interesting questions about generics and delegates that evolved into lua scripts.  Any more in that direction and we should probably start a new thread. Thanks for the cool problems to explore. :)

 

- Eck



#16 satsujin   Members   -  Reputation: 139

Like
0Likes
Like

Posted 20 November 2013 - 09:46 AM

Glad I could inspire you. And thank YOU for sticking with this thread through all my incessant questioning. I'll probably open up a new thread regarding my engine and it's implementation of LuaInterface. Regards....






Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS