I have this code:
class SomeClass {
void someFunction()
{
Action<string> myAction = (what)=>
{
//whatever
}
new List<string>().ForEach(myAction);
}
}
I'd like to extract the code inside myAction into a separate member function.
How do I do that?
class SomeClass
{
void someFunction()
{
Action<string> myAction = Whatever;
new List<string>().ForEach(myAction);
}
public void Whatever(string what)
{
// ... whenever
}
}
or directly, without defining a local Action<string> variable (that will probably be optimized away in Release mode anyway):
new List<string>().ForEach(Whatever);
This should be equivalent:
class SomeClass {
void myAction(string what)
{
// whatever
}
void someFunction()
{
new List<string>().ForEach(item => myAction(item));
}
}
Since Action<string> means a method with a string parameter which does not return a value.
Are you looking for this?
class SomeClass {
void someFunction()
{
new List<string>().ForEach(SeparateMemberFunction);
}
void SeparateMemberFunction(string s)
{
//whatever
}
}
I use a different way:
class SomeClass
{
public void SomeFunction()
{
new List<string>().ForEach(e => this.MyAction(e));
}
private void MyAction(string str){ /* ... */ }
}
I find it clearer because I see at first sight MyActionis a method and not a field or a property
Related
because of this post I create a new question to make my probleme more clear. I have a class with a next class member, so there will be a daisy chain of class instances. A function in my class calls another member function or all instances in the chain.
c ++ has a resonable solution for this problem. In C# I tried it with a delegate. I made a short program to show what I mean.
class Program {
static void Main(string[] args)
{
DaisyChain TestClass = new DaisyChain(1);
TestClass.AddClass(new DaisyChain(2));
TestClass.AllprintID();
}
}
class DaisyChain {
private int ClassID;
private DaisyChain NextClass;
public DaisyChain(int ID) {ClassID = ID; }
public void AddClass(DaisyChain newClass) {
if (NextClass == null) {
NextClass = newClass;
} else {
NextClass.AddClass(newClass);
}
}
public void AllprintID() {
DoForEach(this.printID);
}
public delegate void doFunc();
public void DoForEach (doFunc aMemberFunc) {
aMemberFunc();
if (NextClass != null) {
NextClass.DoForEach(aMemberFunc);
}
}
public void printID() {
Console.WriteLine(ClassID);
}
};
This example do not work correct, because the class instance is not part of the function call.
I can add a class argumnet to my member function and chang the delegate,
public void printID(DaisyChain me) {
Console.WriteLine(me.ClassID);
}
but then the function will be static and no longer usable in the normal way.
I would be happy if ther another solution.
The delegate type should have an extra argument, since you want to call printID on different objects. You can either add one to doFunc, or just use the built in Action<T> delegate type.
public void DoForEach (Action<DaisyChain> aMemberFunc) {
aMemberFunc(this);
if (NextClass != null) {
NextClass.DoForEach(aMemberFunc);
}
}
When calling DoForEach, you can either pass a lambda expression:
public void AllprintID() {
DoForEach(x => x.printID());
}
Or if you really like the method group syntax for some reason, write a local function printID:
public void AllprintID() {
void PrintID(DaisyChain chain) {
chain.PrintID();
}
DoForEach(PrintID);
}
// method names should start with a capital letter :)
public void PrintID() {
Console.WriteLine(ClassID);
}
Other code can still call PrintID as usual - code outside AllprintID won't even notice the local function.
You are trying to reinvent the wheel. Check LinkedList and LinkedListNode in the documentation. Here is an example to get you on the way:
var daisyChain = new DaisyChain();
daisyChain.Add(1);
daisyChain.Add(2);
class DaisyChain: LinkedList<DaisyChainLink>
{
public void Add(int id) => AddLast(new LinkedListNode<DaisyChainLink>(new DaisyChainLink(id)));
public void Print()
{
var link = this.First;
link?.Value.Print();
while (null != link?.Next)
{
link = link.Next;
link?.Value.Print();
}
}
}
class DaisyChainLink
{
public DaisyChainLink(int id)
{
Id = id;
}
public int Id { get; }
public void Print() => Console.WriteLine(Id);
}
In c# if I have this
private void Run(Web site) {
site.BreakRoleInheritance(false, false);
}
private void Run(ListItem folder) {
folder.BreakRoleInheritance(false, false);
}
How can I instead make 1 function that can accept either Site or Folder?
If Site and Folder are classes that you've created, then you can create a common interface which those classes inherit from. For example:
public interface IBreakable
{
void break();
}
public class Folder : IBreakable
{
public void break() { /* implementation here*/ }
}
public class Site : IBreakable
{
public void break() { /* implementation here*/ }
}
Usage
private void Run(IBreakable breakable)
{
breakable.break();
}
Edit
Here's a solution based on reflection, although this is not ideal.
void Run(object obj)
{
MethodInfo method = obj.GetType().GetMethod("break");
if (!(method is null))
{
method.Invoke(obj, new object[] {});
}
}
Given
public class Foo
{
public void break() {Console.WriteLine("Foo");}
}
public class Bar
{
public void break() {Console.WriteLine("Bar");}
}
public class Bad
{
public void NotBreak() {Console.WriteLine("Bad");}
}
Usage
Foo foo = new Foo();
Bar bar = new Bar();
Bad bad = new Bad();
Run(foo);
Run(bar);
Run(bad);
Output
Foo
Bar
As a later answer from #Pedro pointed out, those specific classes derive from a common ancestor, and that would be the preferred option. Assuming you did not have that option:
You can use the C# dynamic type (sorry if that is not the latest doc, I couldn't find a newer one):
https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/types/using-type-dynamic
Example:
using System;
public class Program
{
public static void Main()
{
var foo = new Foo();
var bar = new Bar();
DoSomething(foo);
DoSomething(bar);
}
private static void DoSomething<T>(T someObjectWithDoMethod)
{
((dynamic)someObjectWithDoMethod).Do();
}
}
public class Foo
{
public void Do() { Console.WriteLine("Foo is doing something"); }
}
public class Bar
{
public void Do() { Console.WriteLine("Bar is doing something"); }
}
.Net Fiddle: https://dotnetfiddle.net/MShLK5
Based on your comments to other answers, Web and ListItem are types defined in the Microsoft.SharePoint.Client.
Checking the SDK docs, both types derive from SecurableObject where the BreakRoleInheritance method is defined.
That being the case, all you need to do is define one method that takes a SecurableObject object as an input:
public void Run(SecurableObject item)
{
item.BreakRoleInheritance();
}
And you should be able to pass a Web and a ListItem to this same method.
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 need to get MethodInfo for method called in Action delegate in order to check, whether methods called in Action has MyCustomAttibute
public void Foo( Action action )
{
if(Attribute.GetCustomAttributes(action.Method, typeof(MyCustomAttribute)).Count() == 0)
{
throw new ArgumentException("Invalid action");
}
}
The Foo method should be able to be called as following:
Foo(() =>
{
instanceOfFooClass.Method1().Method2();
});
In Foo method I want to be sure that Method1 and Method2 has MyCustomAttribute. However action.Method is giving me the MethodInfo, which is the action of delegate, which happens when using lambda expression. Is there any way to get Method1 and Method2 MethodInfo?
As mentioned in the comments, Expression<T> is probably the best way to achieve this. However, it requires a Compile() at runtime so it should be performance profiled.
With Expression<T> you can easily get access to Method info like this:
public MethodInfo GetMethodInfo(Expression<Action> action)
{
return ((MethodCallExpression)action.Body).Method;
}
But, before executing the action you must do this:
private void InvokeMethod(Expression<Action> action)
{
action.Compile().Invoke();
}
EDIT
Ah yes, I forgot how to get access to the customer attribute. You would do it like this:
var methodInfo = ((MethodCallExpression)myAction.Body).Method;
var attributes = methodInfo.GetCustomAttributes<T>(true);
EXAMPLE
Here is an example showing passing chained method calls to Expression<Action>:
public class ActionTest
{
public void DoAction(Action action)
{
action();
}
public void DoExpressionAction(Expression<Action> action)
{
var method2Info = ((MethodCallExpression)action.Body).Method;
// a little recursion needed here
var method1Info = ((MethodCallExpression)((MethodCallExpression)action.Body).Object).Method;
var myattributes2 = method2Info.GetCustomAttributes(typeof(MyAttribute), true);
var myattributes1 = method1Info.GetCustomAttributes(typeof(MyAttribute), true);
action.Compile().Invoke();
}
}
[AttributeUsage(AttributeTargets.Method)]
public class MyAttribute : Attribute
{
private string message;
public MyAttribute(string message)
{
this.message = message;
}
}
public class MethodTest
{
[MyAttribute("Number1")]
public MethodTest Method1()
{
Console.WriteLine("Action");
return this;
}
[MyAttribute("Number2")]
public MethodTest Method2()
{
Console.WriteLine("ExpressionAction");
return this;
}
}
class Program
{
static void Main(string[] args)
{
ActionTest target = new ActionTest();
MethodTest instance = new MethodTest();
target.DoExpressionAction(() => instance.Method1().Method2() );
Console.ReadLine();
}
static void Method1()
{
Console.WriteLine("Action");
}
static void Method2()
{
Console.WriteLine("ExpressionAction");
}
}
If you call your Foo() methdod like this:
Foo(instanceOfFooClass.Method);
Your code works as you'd expect (void methods are actions, after all).
On a side note, I think "chaining" method calls in fact counts as you're only passing the last one through.
Full sample demonstrating the behavior:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication4
{
class MyCustomAttribute : Attribute { }
class FooClass
{
[MyCustom]
public void DecoratedMethod() { Console.WriteLine("Decorated Method - executed."); }
public void NotDecoratedMethod() { Console.WriteLine("Not Decoreated Method - executed."); }
}
class Program
{
static void Main(string[] args)
{
FooClass instanceOfFooClass = new FooClass();
Foo(instanceOfFooClass.DecoratedMethod);
Foo(instanceOfFooClass.NotDecoratedMethod);
Console.ReadLine();
}
public static void Foo(Action action)
{
if (Attribute.GetCustomAttributes(action.Method, typeof(MyCustomAttribute)).Count() == 0)
Console.WriteLine(string.Format("Invalid method {0}", action.Method.Name));
else
{
Console.WriteLine(string.Format("Valid method {0}", action.Method.Name));
action.Invoke();
}
}
}
}
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();
}