Is there any way so that you can call a function with a variable?
variable+"()";
or something like that, or would I have to use if statements?
A switch seems like it might be the answer, so if the variable's value=var1 I want it to execute var1(); if the value is var2 I want it to execute var2(); how would I code it?
Basically, I am trying to find a cleaner alternative to
if (variable == var1)
{
var1();
}
if (variable == var2)
{
var2();
}
It would be possible to use reflection to find a method in an object and call that method, but the simplest and fastest would be to simply use a switch:
switch (variable) {
case "OneMethod": OneMethod(); break;
case "OtherMethod": OtherMethod(); break;
}
You could use Reflection http://msdn.microsoft.com/en-us/library/ms173183(v=vs.80).aspx to access any function or member by name. It takes some getting used to though. It also has performance issues, so if you can avoid using it, you should.
This is what delegates are for:
Action f = ()=>Console.WriteLine("foo");
f();
I assume using strings is not actually a requirement.
You can use delegates. MSDN: http://msdn.microsoft.com/en-us/library/900fyy8e(v=vs.71).aspx
Exa:
public delegate void TestDelegate();
class TestDelegate
{
public static void Test()
{
Console.WriteLine("In Test");
}
public static void Main()
{
TestDelegate testDelegate = new TestDelegate(Test);
testDelegate();
}
}
You can use the MethodInfo class
Type yourtype = yourObject.GetType();
MethodInfo method = yourtype.GetMethod(variable);
var result = method.Invoke(yourObject,null);
string className = "My.Program.CoolClass"; //including namespace
string method= "Execute";
var type = Type.GetType(className);
var method = type.GetMethod(method);
method.Invoke(classObj, null);
Check out this post.
Use reflection.
http://dotnetslackers.com/Community/blogs/haissam/archive/2007/07/25/Call-a-function-using-Reflection.aspx
You can use MethodMethodInfo.
http://msdn.microsoft.com/en-us/library/system.reflection.methodinfo.aspx
http://msdn.microsoft.com/en-us/library/a89hcwhh.aspx
Here's a sample how you can call a method via reflection:
public class MyClass
{
public void PrintHello()
{
Console.WriteLine("Hello World");
}
}
//...
public void InvokeMethod(object obj, string method)
{
// call the method
obj.GetType().GetMethod(method).Invoke(obj, null);
}
//...
var o = new MyClass();
var method = "PrintHello";
//...
InvokeMethod(o, method);
(I will complete #Matthew's excellent answer):
var x = (Action) ( ()=>Print("foo") );
x();
p.s. you can fully variable names too:
private Dictionary<string, dynamic> my = new Dictionary<string, dynamic>();
my["x"] = .....
my["x"]();
public class FunctionTest
{
void Main()
{
Action doSomething;
doSomething = FirstFunction;
doSomething();
doSomething = SecondFunction;
doSomething();
}
void FirstFunction()
{
Console.Write("Hello, ");
}
void SecondFunction()
{
Console.Write("World!\n");
}
}
output:
Hello, World!
Doesn't get too much simpler than that.
Related
I found this code (no conpiler error, it's mean code no error) that is "PingCompletedEventHandler" has constructor like PingCompletedEventHandler(abc) with static void abc(object s, PingCompletedEventArgs e){} right?
static PingCompletedEventHandler Ping_completed(object s, PingCompletedEventArgs e)
{
// This code work fine, it used method void abc below
PingCompletedEventHandler a = new PingCompletedEventHandler(abc);
value.Add("abc");
lock (#lock)
{
instances -= 1;
}
if (e.Reply.Status == IPStatus.Success)
{
string abcd = string.Concat("Active IP: ", e.Reply.Address.ToString());
value.Add("abc");
value.Add(abcd);
result += 1;
}
return a;
}
static void abc(object s, PingCompletedEventArgs e)
{
}
How can they do this. I have tested in my code, it doesn't work. Here is my test:
class Class1
{
static void abcd(int a){
}
public
// Error here: Class1.abcd(int)' is a 'method' but is used like a 'type'
Class1(abcd)
{
}
}
class Class3
{
public static void Main()
{
Class1 asd = new Class1();
}
}
When creating event-handlers you provide a pointer to method within the handlers constructor. This is not "a void", it is a delegate pointing to a method of type void.
The constructor therefor should look similar to:
delegate void HandlerMethod(objects s, PingCompletedEventArgs e);
class PingCompletedEventHandler {
PingCompletedEventHandler(HandlerMethod handler) { ... }
}
Now you can call this constructor with new PingCompletedEventHandler(abc) as abc is a method of type void expecting a param of type objectand of of type PingCompletedEventArgs.
Further reading on delegates here on MSDN
EDIT: Since .NET 3.0 there is also the easier to read Action-type that can be used for methods that do not return anything (void). Thus you may also use PingCompletedEventHandler(Action<object, PingCompletedEventArgs> handler) instead of defining your own delegate.
Further EDIT: To get this to work for your test, your constructor for Class1 should look like this: Class1(Action<int> theAction).
When you want a Function as a Parameter of a Method or a Constructor then you have to use a Delegate
The easiest way is using a Action<...> if you have a Void return type or a Func<T, ...> if you have something else as return type.
In your case it will look like this:
public ClassConstructor(Action<YourParameter> myDelegate)
{
}
For Example:
This is a very simple function and you want to create a delegate of this:
private static int Add(int a, int b)
{
return a + b;
}
then you need a delegate that accepts an int as return type and two ints as parameters.
So you define a Func<...> like this and assign the original method:
Func<int, int, int> addDelegate = Add;
the usage is like using Add only with an other name:
var result = addDelegate(2, 5);
I am creating a C# library with some reusable code and was trying to create a method inside a method. I have a method like this:
public static void Method1()
{
// Code
}
What I would like to do is this:
public static void Method1()
{
public static void Method2()
{
}
public static void Method3()
{
}
}
Then I could choose either Method1.Method2 or Method1.Method3. Obviously the compiler isn't happy about this, any help is much appreciated. Thanks.
If by nested method, you mean a method that is only callable within that method (like in Delphi) you could use delegates.
public static void Method1()
{
var method2 = new Action(() => { /* action body */ } );
var method3 = new Action(() => { /* action body */ } );
//call them like normal methods
method2();
method3();
//if you want an argument
var actionWithArgument = new Action<int>(i => { Console.WriteLine(i); });
actionWithArgument(5);
//if you want to return something
var function = new Func<int, int>(i => { return i++; });
int test = function(6);
}
Yes, when C# 7.0 is released, Local Functions will allow you to do that. You will be able to have a method, inside a method as:
public int GetName(int userId)
{
int GetFamilyName(int id)
{
return User.FamilyName;
}
string firstName = User.FirstName;
var fullName = firstName + GetFamilyName(userId);
return fullName;
}
Note that public (and similar modifiers) are not supported C# programming guide:
Because all local functions are private, including an access modifier, such as the private keyword, generates compiler error CS0106, "
This answer was written before C# 7 came out. With C# 7 you can write local methods.
No, you can't do that. You could create a nested class:
public class ContainingClass
{
public static class NestedClass
{
public static void Method2()
{
}
public static void Method3()
{
}
}
}
You'd then call:
ContainingClass.NestedClass.Method2();
or
ContainingClass.NestedClass.Method3();
I wouldn't recommend this though. Usually it's a bad idea to have public nested types.
Can you tell us more about what you're trying to achieve? There may well be a better approach.
You can define delegates within your method with complete code and call them if you want.
public class MyMethods
{
public void Method1()
{
// defining your methods
Action method1 = new Action( () =>
{
Console.WriteLine("I am method 1");
Thread.Sleep(100);
var b = 3.14;
Console.WriteLine(b);
}
);
Action<int> method2 = new Action<int>( a =>
{
Console.WriteLine("I am method 2");
Console.WriteLine(a);
}
);
Func<int, bool> method3 = new Func<int, bool>( a =>
{
Console.WriteLine("I am a function");
return a > 10;
}
);
// calling your methods
method1.Invoke();
method2.Invoke(10);
method3.Invoke(5);
}
}
There is always an alternative of using a nested class within a class that will not be visible from outside and calling its methods, like:
public class SuperClass
{
internal static class HelperClass
{
internal static void Method2() {}
}
public void Method1 ()
{
HelperClass.Method2();
}
}
As of C# 7.0 you can do that:
public static void SlimShady()
{
void Hi([CallerMemberName] string name = null)
{
Console.WriteLine($"Hi! My name is {name}");
}
Hi();
}
This is called local functions, that is just what you were looking for.
I took the example from here, but further informatin can be found here and here.
Why you don't use classes?
public static class Helper
{
public static string MethodA()
{
return "A";
}
public static string MethodA()
{
return "A";
}
}
Now you can acces MethodA via
Helper.MethodA();
Older thread, but C# does have the concept of nested functions
Func<int> getCalcFunction(int total, bool useAddition)
{
int overallValue = 0;
if (useAddition)
{
Func<int> incrementer = new Func<int>(() =>
{
overallValue += total;
return overallValue;
});
return incrementer;
}
else
{
Func<int> decrementer = new Func<int>(() =>
{
overallValue -= total;
return overallValue;
});
return decrementer;
}
}
private void CalcTotals()
{
Func<int> decrem = getCalcFunction(30, false);
int a = decrem(); //result = -30
a = decrem(); //result = -60
Func<int> increm = getCalcFunction(30, true);
int b = increm(); //result = 30
b = increm(); //result = 60
}
Your nearly there
public static void Method1()
should be
public static class Method1{}
Don't you want to use nested class instead?
That's said, you seem to not respect the Single Responsibility Principle because you want a single method do more than one thing at a time.
Why don't you just Run a method within another
public void M1()
{
DO STUFF
}
public void M1()
{
DO STUFF
M1();
}
I am creating a C# library with some reusable code and was trying to create a method inside a method. I have a method like this:
public static void Method1()
{
// Code
}
What I would like to do is this:
public static void Method1()
{
public static void Method2()
{
}
public static void Method3()
{
}
}
Then I could choose either Method1.Method2 or Method1.Method3. Obviously the compiler isn't happy about this, any help is much appreciated. Thanks.
If by nested method, you mean a method that is only callable within that method (like in Delphi) you could use delegates.
public static void Method1()
{
var method2 = new Action(() => { /* action body */ } );
var method3 = new Action(() => { /* action body */ } );
//call them like normal methods
method2();
method3();
//if you want an argument
var actionWithArgument = new Action<int>(i => { Console.WriteLine(i); });
actionWithArgument(5);
//if you want to return something
var function = new Func<int, int>(i => { return i++; });
int test = function(6);
}
Yes, when C# 7.0 is released, Local Functions will allow you to do that. You will be able to have a method, inside a method as:
public int GetName(int userId)
{
int GetFamilyName(int id)
{
return User.FamilyName;
}
string firstName = User.FirstName;
var fullName = firstName + GetFamilyName(userId);
return fullName;
}
Note that public (and similar modifiers) are not supported C# programming guide:
Because all local functions are private, including an access modifier, such as the private keyword, generates compiler error CS0106, "
This answer was written before C# 7 came out. With C# 7 you can write local methods.
No, you can't do that. You could create a nested class:
public class ContainingClass
{
public static class NestedClass
{
public static void Method2()
{
}
public static void Method3()
{
}
}
}
You'd then call:
ContainingClass.NestedClass.Method2();
or
ContainingClass.NestedClass.Method3();
I wouldn't recommend this though. Usually it's a bad idea to have public nested types.
Can you tell us more about what you're trying to achieve? There may well be a better approach.
You can define delegates within your method with complete code and call them if you want.
public class MyMethods
{
public void Method1()
{
// defining your methods
Action method1 = new Action( () =>
{
Console.WriteLine("I am method 1");
Thread.Sleep(100);
var b = 3.14;
Console.WriteLine(b);
}
);
Action<int> method2 = new Action<int>( a =>
{
Console.WriteLine("I am method 2");
Console.WriteLine(a);
}
);
Func<int, bool> method3 = new Func<int, bool>( a =>
{
Console.WriteLine("I am a function");
return a > 10;
}
);
// calling your methods
method1.Invoke();
method2.Invoke(10);
method3.Invoke(5);
}
}
There is always an alternative of using a nested class within a class that will not be visible from outside and calling its methods, like:
public class SuperClass
{
internal static class HelperClass
{
internal static void Method2() {}
}
public void Method1 ()
{
HelperClass.Method2();
}
}
As of C# 7.0 you can do that:
public static void SlimShady()
{
void Hi([CallerMemberName] string name = null)
{
Console.WriteLine($"Hi! My name is {name}");
}
Hi();
}
This is called local functions, that is just what you were looking for.
I took the example from here, but further informatin can be found here and here.
Why you don't use classes?
public static class Helper
{
public static string MethodA()
{
return "A";
}
public static string MethodA()
{
return "A";
}
}
Now you can acces MethodA via
Helper.MethodA();
Older thread, but C# does have the concept of nested functions
Func<int> getCalcFunction(int total, bool useAddition)
{
int overallValue = 0;
if (useAddition)
{
Func<int> incrementer = new Func<int>(() =>
{
overallValue += total;
return overallValue;
});
return incrementer;
}
else
{
Func<int> decrementer = new Func<int>(() =>
{
overallValue -= total;
return overallValue;
});
return decrementer;
}
}
private void CalcTotals()
{
Func<int> decrem = getCalcFunction(30, false);
int a = decrem(); //result = -30
a = decrem(); //result = -60
Func<int> increm = getCalcFunction(30, true);
int b = increm(); //result = 30
b = increm(); //result = 60
}
Your nearly there
public static void Method1()
should be
public static class Method1{}
Don't you want to use nested class instead?
That's said, you seem to not respect the Single Responsibility Principle because you want a single method do more than one thing at a time.
Why don't you just Run a method within another
public void M1()
{
DO STUFF
}
public void M1()
{
DO STUFF
M1();
}
I'm trying to create a url builder similar to the one in asp mvc except our methods are frequently changing parameters and breaking pages.
Does anyone know if it's possible to coerce c# into allowing event like syntax to be returned from a delegate like this:
new UrlBuilder2<FakeController>(x => { return x.ActionWithInt; });
The class would be similar to this:
public class UrlBuilder<TController>
{
public UrlBuilder2(Func<TController, TType> action)
{
}
}
Basically I want to know what Type to use for TType. Or if it's at all possible.
Edit -
I would (if possible) like to use just the method, similar to how you would assign an event ( clickEvent =+ myMethod;)
Not exactly sure what you want to achieve, but assuming you want to generate link simlar to this:
MyForm/MyMethod.aspx
based on WebForm (or any other class) like this:
public class MyForm {
public void MyMethod() {
// Something here
}
public void MethodWithParams(int i, string str) {
// Something here
}
}
You can use this builder (test included):
class UrlBuilder2<T> {
private readonly Expression<Func<T, object>> callExpression;
public UrlBuilder2(Expression<Func<T,object>> callExpression) {
this.callExpression = callExpression;
}
public override string ToString() {
MethodCallExpression call = (MethodCallExpression) callExpression.Body;
StringBuilder sb = new StringBuilder();
sb.AppendFormat("{0}/{1}.aspx", call.Object.Type.Name, call.Method.Name);
var delimiter = "?";
var formalParams = call.Method.GetParameters();
for (int i = 0; i < formalParams.Length; i++) {
var actual = call.Arguments[i];
if (actual == null)
continue; // Do not put NULL to QueryString
var formal = formalParams[i].Name;
sb.AppendFormat("{0}{1}={2}", delimiter, formal, HttpUtility.HtmlEncode(actual.ToString()));
}
return sb.ToString();
}
}
[Test]
public void CanBuildUrlByClassAndMethodName() {
var str = new UrlBuilder2<MyForm>(c => c.MyMethod()).ToString();
str.Should().Be.EqualTo("MyForm/MyMethod.aspx");
}
[Test]
public void CanBuildUrlByMethodWithParams() {
var str = new UrlBuilder2<MyForm>(c => c.MethodWithParams(2, "hello")).ToString();
str.Should().Be.EqualTo("MyForm/MyMethod.aspx?i=2&str=hello");
}
All this will allow you to keep the links type-safe and refactoring advantages will be leveraged.
You will probably need to enhance the UrlBuilder2 but this should get you started.
If you just want to use name of a method to generate links you can do something like this:
class MyClass {
public void MyMethod() {}
}
class UrlBuilder3<T> {
Expression<Func<T, Action>> info;
public UrlBuilder3(Expression<Func<T, Action>> info) {
this.info = info;
}
public override string ToString() {
UnaryExpression exp = (UnaryExpression)info.Body;
MethodCallExpression createDelegate = (MethodCallExpression)exp.Operand;
// 0-Action,1-x,2-Delegate as Constant
ConstantExpression methodArgument = (ConstantExpression)createDelegate.Arguments[2];
MethodInfo method = (MethodInfo)methodArgument.Value;
return string.Format("{0}/{1}.aspx", typeof(T).Name, method.Name);
}
}
[Test]
public void UrlByDelegate() {
new UrlBuilder3<MyClass>(x => x.MyMethod).ToString()
.Should().Be.EqualTo("MyClass/MyMethod.aspx");
}
The tricky thing is correctly resolving the Expression tree. The code above works for this particular sample, but you will need to check it works for all your cases.
You can return a function pointer aka a delegate in c# as below.
public delegate int mydelegate(string s);
public class Test
{
mydelegate MyFunc(string s)
{
return (astring => astring.Length + s.Length);
}
}
This would allow you to attach the output of the function to an event.
var test = new Test();
someevent += test.MyFunc("this is a test");
Assuming that someevent took a function with the same signature as the delegate.
Is there a pattern that I could apply to refactor this code? The only difference between the two methods is that that one method takes an extra parameter and passes it to the delegate?
I found out that delegates cannot take overloaded method signatures. How could I add one more level of indirection? :)
public static void ProcessFolder(
ProcessFolderDelegate processFolderDelegate
)
{
using (var esb = ExchangeService.GetExchangeServiceBinding())
{
var contactFolder = FolderService.GetPublicFolder(esb,
Properties.Settings.Default.ExchangePublicFolderName);
processFolderDelegate(esb, contactFolder);
}
}
public static void ProcessContact(
ProcessContactDelegate processContactDelegate,
Contact contact //extra param
)
{
using (var esb = ExchangeService.GetExchangeServiceBinding())
{
var contactFolder = FolderService.GetPublicFolder(esb,
Properties.Settings.Default.ExchangePublicFolderName);
processContactDelegate(esb, contactFolder, contact); //extra param
}
}
public delegate void Action(TYPE_OF_ESB esb, TYPE_OF_CONTACT_FOLDER contact folder);
private static void Process(Action action)
{
using (var esb = ExchangeService.GetExchangeServiceBinding())
{
var contactFolder = FolderService.GetPublicFolder(esb, Properties.Settings.Default.ExchangePublicFolderName);
action(esb, contactfolder);
}
}
Process((esb, contactfolder)=>processFolderDelegate(esb, contactFolder));
Process((esb, contactfolder)=>processContactDelegate(esb, contactFolder, contact));
No, the code you posted is actually a very terse method of applying this patter. You're not going to find a terser way unless there is some way of abstracting the type of method being called, or by removing all type safety, which I would not recommend
public static void ProcessFolder(ProcessFolderDelegate del)
{
Process((b, f) => del(b, f));
}
public static void ProcessContact(ProcessContactDelegate del, Contact contact)
{
Process((b, f) => del(b, f, contact));
}
private static void Process(
Action<ExchangeServiceBinding, ContactsFolderType> action)
{
// i've guessed that esb is of type ExchangeServiceBinding
// and that contactFolder is of type ContactsFolderType
// if that's not the case then change the type parameters
// of the Action delegate in the method signature above
using (var esb = ExchangeService.GetExchangeServiceBinding())
{
var contactFolder = FolderService.GetPublicFolder(
esb, Properties.Settings.Default.ExchangePublicFolderName);
action(esb, contactFolder);
}
}
You could use anonymous methods or lambdas like this:
delegate void ProcessDelegate<T>(T param);
.
.
public static void Process<T>(ProcessDelegate<T> processDelegate)
{
using (var esb = ExchangeService.GetExchangeServiceBinding())
{
var contactFolder = FolderService.GetPublicFolder(esb,
Properties.Settings.Default.ExchangePublicFolderName);
processDelegate(contactFolder);
}
}
and then call the method like this
Process(contactFolder => MyMethod(esb, contactFolder));
Process(contactFolder => MyMethod(esb, contactFolder, contact));
Where MyMethod is the actual method you're calling, so you contain it within your lambda expression rather than a delegate. Think something like that may work?