I dont think I understand the point of a delegate method. All the examples I have seen do something like this:
class DelegateClass
{
private List<string> ListString = new List<string>;
delegate void DoSomethingToStringsDelegate(string s);
public base()
{
ListString.Add("string"); ....
}
void ProcessStrings(DoSomethingToStringsDelegate dstsd)
{
foreach(string s in ListString)
dstsd(s);
}
}
class AClass
{
...
void UseDelegateMethod(...)
{
DelegateClass ds = new DelegateClass();
ds.ProcessStrings(new DoSomethingToStringsDelegate(PrintStrings);
}
void PrintStrings(string s)
{
System.out.Write(s);
}
}
I dont understand why this is needed when you could simply just implement a getListStrings() and iterate through the strings yourself, doing what you needed to do, as if it was a delegate.
foreach( string s in ds.ggetListStrings() )
System.out.Write(s);
Private members reason doesnt make sense because I could just do:
global List<Strings> myListStrings = new List<Strings>();
ds.ProcessStrings(new DoSomethingToStringsDelegate(GetStrings);
void GetStrings(string s)
{
myListStrings.Add(s);
}
...and now I have the same list, as a getListStrings() would do ....
Can someone please explain? Thanks so much!
The delegate is useful because it actually acts as a placeholder for any method that takes a string as parameter and returns void.
If you are familiar with C, it is similar to how a function pointer works. In its place you can pass any method that matches the signature and return type.
For example let's say I want to implement a method that sorts a group of objects. In addition to the object list I can also pass a delegate that indicates how the sort is to be done. Since any method matching the delegate can be passed, I can then dynamically switch between different methods if I want for example decreasing or increasing sort:
delegate int comparisonDelegate(int p1, int p2);
void SortArray(int[] array, comparisonDelegate cmp)
{
// determine order according to cmp
}
int CompareDecreasing(int p1, int p2)
{
if(p1 > p2) return -1;
if(p1 < p2) return 1;
return 0;
}
int CompareIncreasing(int p1, int p2)
{
if(p1 > p2) return 1;
if(p1 < p2) return -1;
return 0;
}
Now I can call SortArray as:
SortArray(array, new comparisonDelegate(compareDecreasing));
SortArray(array, new comparisonDelegate(compareIncreasing));
I dont understand why this is needed when you could simply just implement a getListStrings() and iterate through the strings yourself, doing what you needed to do, as if it was a delegate.
The goal here is to make a function that will work on the collection, but do any operation.
This is easier to grasp by example - to see a great example of how and why this is useful, look at LINQ to Objects.
Suppose you want to see how many of your strings are greater than 4 characters - the Enumerable.Count method has an overload that takes a delegate - a Func<T,bool> predicate that can be used. This lets you specify any operation and count the elements, ie:
List<string> listOfStrings = GetListOfStrings();
int countOfStringsGreaterThanFourChars = listOfStrings.Count(s => s.Length > 4);
Here, we're passing a delegate (created via a lambda expression) that gives us our criteria. By having a Count method that takes a delegate, it works for any criteria, so we don't have to reimplement this every time we want a different condition.
Say we want to see how many strings start with "E", we could just use:
int countOfStringsStartingWithE = listOfStrings.Count(s => s.StartsWith("E"));
Again, we only have to write the code that's relevant to our specific need, not duplicate all of the boilerplate code that would be required to loop through our collection and count the items...
Using a delegate in your illustration allows you to change out the implementation of the method.
A better example is that of a Comparer method. I won't get into the IComparer interface, but suffice it to say that, using a delegate, you would be able to modify a sort method's behavior by passing it a delegate to a comparison function.
http://msdn.microsoft.com/en-us/library/system.collections.icomparer.aspx
For one, it allows you to inject different behaviors with the same method signature. In one case you might want to simply add to your list. In another case you might want to add to the list and write to a log file, or whatever else you might want to do in a DoSomethingToStringsDelegate.
Think of it in terms of events. Say you have a class that does some processing on a list of items, and for each item, someone consuming your class may want to be notified that an item has been processed (maybe update a progress bar, or update some other part of the system, whatever). Let's put delegates aside for a second, and let's see how we can implement this using interfaces:
public class MyClassThatDoesSomething
{
private List<string> list = new List<string>();
public void ProcessList()
{
foreach(var item in list)
{
ProcessItem(item);
//how do we notify someone here??
}
}
private void ProcessItem(string item){}
}
Now say someone is consuming this class:
var mc = new MyClassThatDoesSomething();
mc.ProcessList(); //how do I know when each one has been processed?
So solve this problem, let's create an interface:
public interface IItemProcessed
{
void ItemProcessed(string item);
}
We can now refactor our original class:
public class MyClassThatDoesSomething
{
private List<string> list = new List<string>();
public void ProcessList()
{
foreach(var item in list)
{
ProcessItem(item);
//how do we notify someone here??
if(this.Listener != null)
{
this.Listener.ItemProcessed(item);
}
}
}
private void ProcessItem(string item){}
public IItemProcessed Listener {get;set;}
}
and the consumer of your class can now do this:
public class ProcessListener : IItemProcessed
{
public void ItemProcessed(string item)
{
Console.WriteLine(item);
//update progress bar, whatever
}
}
var mc = new MyClassThatDoesSomething();
mc.Listener = new ProcessListener();
mc.ProcessList();
Now that you understand that, you can think of delegates as mini interfaces, and you can then change your original class to this:
public class MyClassThatDoesSomething
{
private List<string> list = new List<string>();
public void ProcessList()
{
foreach(var item in list)
{
ProcessItem(item);
//how do we notify someone here??
if(this.Callback != null)
{
this.Callback(item);
}
}
}
private void ProcessItem(string item){}
public Action<string> Callback {get;set;}
}
and the consumer:
var mc = new MyClassThatDoesSomething();
mc.Listener = s =>
{
Console.WriteLine(s);
//update progress bar, whatever
}
mc.ProcessList();
To summarize, you can think of delegates as a way to provide outsiders a simple "hook" into your code to either let them provide small pieces of logic (think of Linq and filtering a collection) or for callbacks/events like I've demonstrated above.
Related
I'm trying to reduce the duplicate code by combining two tests validation methods. Both test methods pass three parameters (actualResponse, expectedReponse, filterParams) but the problem is that even if the two methods have define the same name for parameters their datatype are different.
Here is the summary of the script:
TestSteps.cs class where these methods are called:
public class TestSteps : BaseTest
{
// _result holds the actual results coming from context get cal
private Context _result = new();
// _SolutionExpectedResponse have expected response from json file.
private readonly Context _SolutionExpectedResponse = new();
public TestSteps()
{
string jsonstring = File.ReadAllText(#Path of response.json file);
_SolutionExpectedResponse = JsonConvert.DeserializeObject<Context>(jsonstring);
}
[When(#Call context api)]
public void WhenCallContextAPI()
{
_result = Context.GetAsync(token,resource).Result;
}
[Then(#Verify the response Values)]
public void ThenVerifyTheResponseValues()
{
ValidateDataValues(_result.Data, _SolutionExpectedResponse.Data, new string[] {"data"})
ValidateSensitiveDataValues(_result.SensitiveData, _SolutionExpectedResponse.SensitiveData, new string[] {"sensitiveData"})
}
}
BaseTest.cs class where validate methods were wrote:
Method #1:
Protected void ValidateDataValues(List<DataReadable> actualResponse, List <DataReadable> expectedResponse, string[] filterParams)
{
if (filterParams.contains("data"))
{
if(actualResponse !=null)
{
for(int i=0; i < expectedResponse.Count; i++)
{
if((actualResponse[i].Key !=null)
{
actualResponse[i].Key.Value.ToString().Should.BeEquivalentTo(expectedResponse[i].Key.Value.ToString());
}
}
return;
}
else
{
actualResponse.Should().BeNull();
}
}
}
Method #2:
Protected void ValidateSensitiveDataValues(List<SensitiveDataReadable> actualResponse, List <SensitiveDataReadable> expectedResponse, string[] filterParams)
{
if (filterParams.contains("sensitiveData"))
{
if(actualResponse !=null)
{
for(int i=0; i < expectedResponse.Count; i++)
{
if((actualResponse[i].Key !=null)
{
actualResponse[i].Key.Value.ToString().Should.BeEquivalentTo(expectedResponse[i].Key.Value.ToString());
}
}
return;
}
else
{
actualResponse.Should().BeNull();
}
}
}
Is it possible for me to reduce the duplicate code by adding method#2 parameters in method#1 and eliminating method #2?
OR
By calling method #1 from the method #2 by converting the datatype?
A typical approach would be to use generics, this lets you define a method that can take any type, or some subset of types as parameters:
public bool ValidateSensitiveDataValues<T>(IEnumerable<T> actual, IEnumerable<T> expected, IEqualityComparer<T> comparer){
return actual.SequenceEqual(expected, comparer);
}
Note that if T is a class you either need to give the method a EqualityComparer-object, or restrict the method to only work if T implements IEquatable: ValidateSensitiveDataValues<T>(IEnumerable<T> actual, IEnumerable<T> expected) where T : IEquatable<T>. I tend to prefer the former since it is more flexible. If you do not do this any reference objects will use reference equality, and that is probably not what you want.
You might also want to use a unit test library. NUnit is a poppular one that has Assert-methods like CollectionAssert.AreEqual and CollectionAssert.AreEquivalent. Where only the former care about ordering of the items.
I have several methods all with the same parameter types and return values but different names and blocks. I want to pass the name of the method to run to another method that will invoke the passed method.
public int Method1(string)
{
// Do something
return myInt;
}
public int Method2(string)
{
// Do something different
return myInt;
}
public bool RunTheMethod([Method Name passed in here] myMethodName)
{
// Do stuff
int i = myMethodName("My String");
// Do more stuff
return true;
}
public bool Test()
{
return RunTheMethod(Method1);
}
This code does not work but this is what I am trying to do. What I don't understand is how to write the RunTheMethod code since I need to define the parameter.
You can use the Func delegate in .NET 3.5 as the parameter in your RunTheMethod method. The Func delegate allows you to specify a method that takes a number of parameters of a specific type and returns a single argument of a specific type. Here is an example that should work:
public class Class1
{
public int Method1(string input)
{
//... do something
return 0;
}
public int Method2(string input)
{
//... do something different
return 1;
}
public bool RunTheMethod(Func<string, int> myMethodName)
{
//... do stuff
int i = myMethodName("My String");
//... do more stuff
return true;
}
public bool Test()
{
return RunTheMethod(Method1);
}
}
You need to use a delegate. In this case all your methods take a string parameter and return an int - this is most simply represented by the Func<string, int> delegate1. So your code can become correct with as simple a change as this:
public bool RunTheMethod(Func<string, int> myMethodName)
{
// ... do stuff
int i = myMethodName("My String");
// ... do more stuff
return true;
}
Delegates have a lot more power than this, admittedly. For example, with C# you can create a delegate from a lambda expression, so you could invoke your method this way:
RunTheMethod(x => x.Length);
That will create an anonymous function like this:
// The <> in the name make it "unspeakable" - you can't refer to this method directly
// in your own code.
private static int <>_HiddenMethod_<>(string x)
{
return x.Length;
}
and then pass that delegate to the RunTheMethod method.
You can use delegates for event subscriptions, asynchronous execution, callbacks - all kinds of things. It's well worth reading up on them, particularly if you want to use LINQ. I have an article which is mostly about the differences between delegates and events, but you may find it useful anyway.
1 This is just based on the generic Func<T, TResult> delegate type in the framework; you could easily declare your own:
public delegate int MyDelegateType(string value)
and then make the parameter be of type MyDelegateType instead.
From OP's example:
public static int Method1(string mystring)
{
return 1;
}
public static int Method2(string mystring)
{
return 2;
}
You can try Action Delegate! And then call your method using
public bool RunTheMethod(Action myMethodName)
{
myMethodName(); // note: the return value got discarded
return true;
}
RunTheMethod(() => Method1("MyString1"));
Or
public static object InvokeMethod(Delegate method, params object[] args)
{
return method.DynamicInvoke(args);
}
Then simply call method
Console.WriteLine(InvokeMethod(new Func<string,int>(Method1), "MyString1"));
Console.WriteLine(InvokeMethod(new Func<string, int>(Method2), "MyString2"));
In order to provide a clear and complete answer, I'm going to start from the very beginning before showing three possible solutions.
A brief introduction
All .NET languages (such as C#, F#, and Visual Basic) run on top of the Common Language Runtime (CLR), which is a VM that runs code in the Common Intermediate Language (CIL), which is way higher level than machine code. It follows that methods aren't Assembly subroutines, nor are they values, unlike functional languages and JavaScript; rather, they're symbols that CLR recognizes. Not being values, they cannot be passed as a parameter. That's why there's a special tool in .NET. That is, delegates.
What's a delegate?
A delegate represents a handle to a method (the term handle is to be preferred over pointer as the latter would be an implementation detail). Since a method is not a value, there has to be a special class in .NET, namely Delegate, which wraps up any method. What makes it special is that, like very few classes, it needs to be implemented by the CLR itself and couldn't be simply written as a class in a .NET language.
Three different solutions, the same underlying concept
The type–unsafe way
Using the Delegate special class directly.
Example:
static void MyMethod()
{
Console.WriteLine("I was called by the Delegate special class!");
}
static void CallAnyMethod(Delegate yourMethod)
{
yourMethod.DynamicInvoke(new object[] { /*Array of arguments to pass*/ });
}
static void Main()
{
CallAnyMethod(MyMethod);
}
The drawback here is your code being type–unsafe, allowing arguments to be passed dynamically, with no constraints.
The custom way
Besides the Delegate special class, the concept of delegates spreads to custom delegates, which are declarations of methods preceded by the delegate keyword. They are type–checked the same way as “normal” method invocations, making for type-safe code.
Example:
delegate void PrintDelegate(string prompt);
static void PrintSomewhere(PrintDelegate print, string prompt)
{
print(prompt);
}
static void PrintOnConsole(string prompt)
{
Console.WriteLine(prompt);
}
static void PrintOnScreen(string prompt)
{
MessageBox.Show(prompt);
}
static void Main()
{
PrintSomewhere(PrintOnConsole, "Press a key to get a message");
Console.Read();
PrintSomewhere(PrintOnScreen, "Hello world");
}
The standard library's way
Alternatively, you can stick with a delegate that's part of the .NET Standard:
Action wraps up a parameterless void method;
Action<T1> wraps up a void method with one parameter of type T1;
Action<T1, T2> wraps up a void method with two parameters of types T1 and T2, respectively,
and so forth;
Func<TR> wraps up a parameterless function with TR return type;
Func<T1, TR> wraps up a function with TR return type and with one parameter of type T1;
Func<T1, T2, TR> wraps up a function with TR return type and with two parameters of types T1 and T2, respectively;
and so forth.
However, bear in mind that by using predefined delegates like these, parameter names won't be self-describing, nor is the name of the delegate type meaningful as to what instances are supposed to do. Therefore, refrain from using them in contexts where their purpose is not absolutely self-evident.
The latter solution is the one most people posted. I'm also mentioning it in my answer for the sake of completeness.
The solution involves Delegates, which are used to store methods to call. Define a method taking a delegate as an argument,
public static T Runner<T>(Func<T> funcToRun)
{
// Do stuff before running function as normal
return funcToRun();
}
Then pass the delegate on the call site:
var returnValue = Runner(() => GetUser(99));
You should use a Func<string, int> delegate, that represents a function taking a string argument and returning an int value:
public bool RunTheMethod(Func<string, int> myMethod)
{
// Do stuff
myMethod.Invoke("My String");
// Do stuff
return true;
}
Then invoke it this way:
public bool Test()
{
return RunTheMethod(Method1);
}
While the accepted answer is absolutely correct, I would like to provide an additional method.
I ended up here after doing my own searching for a solution to a similar question.
I am building a plugin driven framework, and as part of it I wanted people to be able to add menu items to the applications menu to a generic list without exposing an actual Menu object because the framework may deploy on other platforms that don't have Menu UI objects. Adding general info about the menu is easy enough, but allowing the plugin developer enough liberty to create the callback for when the menu is clicked was proving to be a pain. Until it dawned on me that I was trying to re-invent the wheel and normal menus call and trigger the callback from events!
So the solution, as simple as it sounds once you realize it, eluded me until now.
Just create separate classes for each of your current methods, inherited from a base if you must, and just add an event handler to each.
Here is an example Which can help you better to understand how to pass a function as a parameter.
Suppose you have Parent page and you want to open a child popup window. In the parent page there is a textbox that should be filled basing on child popup textbox.
Here you need to create a delegate.
Parent.cs
// declaration of delegates
public delegate void FillName(String FirstName);
Now create a function which will fill your textbox and function should map delegates
//parameters
public void Getname(String ThisName)
{
txtname.Text=ThisName;
}
Now on button click you need to open a Child popup window.
private void button1_Click(object sender, RoutedEventArgs e)
{
ChildPopUp p = new ChildPopUp (Getname) //pass function name in its constructor
p.Show();
}
IN ChildPopUp constructor you need to create parameter of 'delegate type' of parent //page
ChildPopUp.cs
public Parent.FillName obj;
public PopUp(Parent.FillName objTMP)//parameter as deligate type
{
obj = objTMP;
InitializeComponent();
}
private void OKButton_Click(object sender, RoutedEventArgs e)
{
obj(txtFirstName.Text);
// Getname() function will call automatically here
this.DialogResult = true;
}
If you want to pass Method as parameter, use:
using System;
public void Method1()
{
CallingMethod(CalledMethod);
}
public void CallingMethod(Action method)
{
method(); // This will call the method that has been passed as parameter
}
public void CalledMethod()
{
Console.WriteLine("This method is called by passing it as a parameter");
}
If the method passed needs to take one argument and return a value, Func is the best way to go. Here is an example.
public int Method1(string)
{
// Do something
return 6;
}
public int Method2(string)
{
// Do something different
return 5;
}
public bool RunTheMethod(Func<string, int> myMethodName)
{
// Do stuff
int i = myMethodName("My String");
Console.WriteLine(i); // This is just in place of the "Do more stuff"
return true;
}
public bool Test()
{
return RunTheMethod(Method1);
}
Read the docs here
However, if your method that is passed as a parameter does not return anything, you can also use Action. It supports up to 16 paramaters for the passed method. Here is an example.
public int MethodToBeCalled(string name, int age)
{
Console.WriteLine(name + "'s age is" + age);
}
public bool RunTheMethod(Action<string, int> myMethodName)
{
// Do stuff
myMethodName("bob", 32); // Expected output: "bob's age is 32"
return true;
}
public bool Test()
{
return RunTheMethod(MethodToBeCalled);
}
Read the documentation here
Here is an example without a parameter:
http://en.csharp-online.net/CSharp_FAQ:_How_call_a_method_using_a_name_string
with params:
http://www.daniweb.com/forums/thread98148.html#
you basically pass in an array of objects along with name of method. you then use both with the Invoke method.
params Object[] parameters
class PersonDB
{
string[] list = { "John", "Sam", "Dave" };
public void Process(ProcessPersonDelegate f)
{
foreach(string s in list) f(s);
}
}
The second class is Client, which will use the storage class. It has a Main method that creates an instance of PersonDB, and it calls that object’s Process method with a method that is defined in the Client class.
class Client
{
static void Main()
{
PersonDB p = new PersonDB();
p.Process(PrintName);
}
static void PrintName(string name)
{
System.Console.WriteLine(name);
}
}
I don't know who might need this, but in case you're unsure how to send a lambda with a delegate, when the function using the delegate doesn't need to insert any params in there you just need the return value.
SO you can also do this:
public int DoStuff(string stuff)
{
Console.WriteLine(stuff);
}
public static bool MethodWithDelegate(Func<int> delegate)
{
///do stuff
int i = delegate();
return i!=0;
}
public static void Main(String[] args)
{
var answer = MethodWithDelegate(()=> DoStuff("On This random string that the MethodWithDelegate doesn't know about."));
}
I have two separate methods, where the meat of the method is as follows:
StringBuilder sb = new StringBuilder();
foreach(FooItem I in inventory)
{
sb.AppendFormat("{0},{1}…", i.Name, i.Volume);
}
File.WriteAllText(filename, sb.ToString();
So the in one method I have i.Volume, in another it is i.Price. The ONLY difference between the two methods are the property of the object in the list that is being used to output.
So the question is how can I abstract this out where I can tell it which property I want to use in from the given caller?
You don't need to abstract them, just write one by one using LINQ, usually we don't abstract one-line codes.
var volumeOutput = string.Join("...", volumnObjects.Select(x => $"{x.Name},{x.Volumn}"));
var priceOutput = string.Join("...", priceObjects.Select(x => $"{x.Name},{x.Price}"));
The only difference is your original program has "..." after the last item, I don't know if it's what you want.
Based on what you said i assume you already have a predefined way of choosing which property to write for a given object.Making this assumption :
class FooItem
{
public string Name{get;set;}
public double Volume{get;set;}
}
public void WriteFoos(IEnumerable<(string,FooItem)>inventory,string fileName){
StringBuilder sb = new StringBuilder();
foreach(var item in inventory) {
WriteFoo(item,sb);
}
File.WriteAllText(fileName,sb);
}
public void WriteFoo((FooItem item,string property)pair,StringBuilder sb){
object value=ChooseProperty(pair);
sb.AppendFormat("{0},{1}", pair.property,value);
}
public object ChooseProperty((FooItem item,string property)pair){
switch(property){
case "Volume":return pair.item.Volume;
case "Name":return pair.item.Name;
}
}
P.S Choosing the property based on a given string with a switch-case is the most easy way.If you want something generic (without having to write the switch-case you can change the ChooseProperty using System.Reflection like:
public object ChooseProperty((FooItem item,string property)pair){
PropertyInfo prop=pair.item.GetType().GetProperty(pair.property);
object value=prop.GetValue(item);
return value;
}
This however will cause you a performance hit.Another variant is to use System.Linq.Expressions
There are other ways of doing this. However, you could use a Func<T,U>
Basically every time you call getProp(item), it will ask for what you passed in the lambda expression`
private void SomeMethod<T>(IEnumerable<Inventory> source, Func<Inventory,T> getProp)
{
var sb = new StringBuilder();
foreach(var item in source)
{
sb.AppendFormat("{0},{1}…", item.Name, getProp(item));
}
File.WriteAllText(filename, sb.ToString());
}
Usage
var list = new List<Inventory>();
...
SomeMethod(list, x => x.Volume);
SomeMethod(list, x => x.Price);
Additional Resources
Func Delegate
Encapsulates a method that has one parameter and returns a value of
the type specified by the TResult parameter.
For example, I have a code fragment like this:
IEnumerable<int> _en;
object _lock = new Object();
void Enumerate()
{
IEnumerable<int> en = null;
lock (_lock)
{
en = _en;
_en = new List<int>();
// ...
}
foreach (var i in en)
{
// ...
}
}
I want to change the item type from int to double, so I have at least 3 places to attend and change it. To facilitate this, does something like the following make sense? Is there anything else I can do?
IEnumerable<int> _en;
object _lock = new Object();
void Enumerate()
{
var en = GetDefault(_en);
lock (_lock)
{
en = _en;
_en = CreateEmptyList(_en);
// ...
}
foreach (var i in en)
{
// ...
}
}
static T GetDefault<T>(T arg)
{
return default(T);
}
static List<T> CreateEmptyList<T>(IEnumerable<T> arg)
{
return new List<T>();
}
The Problem:
As I have decided to understand it, you want to minimize effort of menial refactoring tasks amongst constantly changing requirements in your work environment by creating some way of lowering the number of overall places you'd need to change code during this refactoring.
One Possible Solution:
You can obfuscate to a point.
Important Note: Places where your code is called may have to be refactored if you want to change from, double to int. Basically covariance and contravariance comes into play.
double example = 2; // works
int example2 = 2.5; // needs to manually be refactored
So with that in mind, you can create your class as a generic base class that accepts a value type and you'd then create a pass-through subclass that defines that value type (int, double, etc.).
You'd want to provide methods that don't require the explicit creation of, say List all over the place because then when refactoring, all that has to be changed.
Here's an example of a method that can do something like this:
// We use params T[] here to reduce the need for any calling code to declare,
// for example, a List<int>, which would later need to potentially be changed in
// many places.
public void SetEnumerable(params T[] value)
{
_en = value;
}
And you would call it with just the numeric values: (As per my first note, if you change the underlying generic type from int to double, this will continue to work; however if you change from double to int, then the calling code won't compile until it is refactored.
Example:
// Here we use the SetEnumerable method without declaring a List<int>.
// Therefore, if you later change underlying type to double, the code
// below can remain unchanged.
var myEnumerable = new MyEnumerable();
myEnumerable.SetEnumerable(1, 2, 3);
The class structure could look something like this:
Note I'm not suggesting this is a great practice, and am merely attempting to provide a possible solution to your distinct problem in this case. The merits of this solution in terms of performance and/or whether it's a good idea are outside the scope of this answer :)
public class MyEnumerable : EnumerateBase<int> { }
public class EnumerateBase<T> where T : struct
{
private IEnumerable<T> _en;
object _lock = new Object();
public void SetEnumerable(params T[] value)
{
_en = value;
}
public void Enumerate()
{
IEnumerable<T> en = null;
lock (_lock)
{
en = _en;
_en = new List<T>();
// ...
}
foreach (var i in en) { /* ... */ }
}
}
In this example, the datatype int is only declared in one place, making refactoring relatively simple.
Hopefully, this gives you some food for thought and insight into how to approach your stated problem.
I have a series of functions that I want to have the following functionality.
When the function is called, add itself to a list of functions remembering the parameters and values
Allow the list of functions to be called at a later date
The different functions have a variety of different parameters and I'm struggling to think of an elegant way to do this. Any help would be appreciated.
I think this would meet your needs, however the functions are not "adding themselves".
public class Recorder
{
private IList<Action> _recording;
public Recorder()
{
_recording = new List<Action>();
}
public void CallAndRecord(Action action)
{
_recording.Add(action);
action();
}
public void Playback()
{
foreach(var action in _recording)
{
action();
}
}
}
//usage
var recorder = new Recorder();
//calls the functions the first time, and records the order, function, and args
recorder.CallAndRecord(()=>Foo(1,2,4));
recorder.CallAndRecord(()=>Bar(6));
recorder.CallAndRecord(()=>Foo2("hello"));
recorder.CallAndRecord(()=>Bar2(0,11,true));
//plays everything back
recorder.Playback();
One way to make the functions "add themselves" would be to use an AOP lib such as postsharp or linfu dynamic proxy, and add an interceptor which adds the function and args to the array. To do this would probably be more work than it would be worth IMO, as the above is much simpler and still achieves the desired functionality.
There's hardly an elegant solution to this. Since you said the methods would all have different signature, there's no way to store them in a single array as delegates. With that out of the way, next you can try is using reflection, storing each parameter value in object[], storing the method as MethodInfo, and then invoking it.
Edit: This is what I could come up with:
private Dictionary<MethodBase, object[]> methodCollection = new Dictionary<MethodBase, object[]>();
public void AddMethod(MethodBase method, params object[] arguments)
{
methodCollection.Add(method, arguments);
}
private void MyMethod(int p1, string p2, bool p3)
{
AddMethod(System.Reflection.MethodInfo.GetCurrentMethod(), new object[] { p1, p2, p3 });
}
private void MyOtherMethod()
{
AddMethod(System.Reflection.MethodInfo.GetCurrentMethod(), new object[] { });
}
Then just invoke with method.Invoke(method.ReflectedType, args)
Maybe you could some how use the Delegate.DynamicInvoke(Object[] obj) function. You could add each method to an object array, then loop through the array calling DynamicInvoke on each one.
I'm not sure I understand your question, but I think you could use array of pointers to a functions(in C# it is called delegates). So when function is called, put function pointer in a list. In this way you can call function from list. Here is some idea. Notice when you add new delegate pointer to a list (functionPointers), in second list myParameters you add new object of type Parameters which holds function parameters in public attribute called parameters. This means that delegate i in list functionPointers for parameters has i-th object in list myParameters. This is how you know which parameters, are for which function. Probably there are some betters solutions, but this is alternative.
delegate void NewDelegate();
class Parameter{
public ArrayList parameters;
}
ArrayList functionPointers=new ArrayList();
ArrayList<Parameter> myParameters=new ArrayList<Parameter>();
NewDelegate myDelegate;
void someFunction(int a, int b){
myDelegate+=someFunction;//you add this function to delegate because this function is called
functionPointers.add(myDelegate);//Add delegete to list
Parameter p=new Parameter();//Create new Parameter object
p.parameters.add(a);//Add function parameters
p.parameters.add(b);
myParameters.add(p);//add object p to myParameters list
}
You could consider using a list of actions or functions
using System;
using System.Collections.Generic;
namespace ReplayConsole
{
class Program
{
private static IList<Action> _actions;
static void Main(string[] args)
{
_actions = new List<Action>
{
() => {
//do thing
},
() => {
//do thing
},
() => {
//do thing
},
() => {
//do thing
},
};
foreach (var action in _actions)
{
action();
}
}
}
if you want to store parameters as well and have you could use a Func and store and use it in much the same way
You could also look at Tasks
EDIT:
looking at the answers that popped up while I was writing mine this solution is very similar to Brook's