Can a method be overriden with a lambda function - c#

Is there any way to override a class method with a lambda function?
For example with a class definition of
class MyClass {
public virtual void MyMethod(int x) {
throw new NotImplementedException();
}
}
Is there anyway to do:
MyClass myObj = new MyClass();
myObj.MyMethod = (x) => { Console.WriteLine(x); };

Chris is right that methods cannot be used like variables. However, you could do something like this:
class MyClass {
public Action<int> MyAction = x => { throw new NotImplementedException() };
}
To allow the action to be overridden:
MyClass myObj = new MyClass();
myObj.MyAction = (x) => { Console.WriteLine(x); };

No. However if you declare the method as a lambda in the first place, you can set it, though I would try to do that at initialization time.
class MyClass {
public MyClass(Action<int> myMethod)
{
this.MyMethod = myMethod ?? x => { };
}
public readonly Action<int> MyMethod;
}
This however cannot implement an interface that has a MyMethod declared, unless the interface specifies a lambda property.
F# has object expressions, which allow you to compose an object out of lambdas. I hope at some point this is part of c#.

No. Methods cannot be used like variables.
If you were using JavaScript, then yes, you could do that.

You can write this code:
MyClass myObj = new MyClass();
myObj.TheAction = x => Console.WriteLine(x);
myObj.DoAction(3);
If you define MyClass in this way:
class MyClass
{
public Action<int> TheAction {get;set;}
public void DoAction(int x)
{
if (TheAction != null)
{
TheAction(x);
}
}
}
But that shouldn't be too surprising.

Not directly, but with a little code it's doable.
public class MyBase
{
public virtual int Convert(string s)
{
return System.Convert.ToInt32(s);
}
}
public class Derived : MyBase
{
public Func<string, int> ConvertFunc { get; set; }
public override int Convert(string s)
{
if (ConvertFunc != null)
return ConvertFunc(s);
return base.Convert(s);
}
}
then you could have code
Derived d = new Derived();
int resultBase = d.Convert("1234");
d.ConvertFunc = (o) => { return -1 * Convert.ToInt32(o); };
int resultCustom = d.Convert("1234");

Depending on what you want to do, there are many ways to solve this problem.
A good starting point is to make a delegate (e.g. Action) property that is gettable and settable. You can then have a method which delegates to that action property, or simply call it directly in client code. This opens up a lot of other options, such as making the action property private settable (perhaps providing a constructor to set it), etc.
E.g.
class Program
{
static void Main(string[] args)
{
Foo myfoo = new Foo();
myfoo.MethodCall();
myfoo.DelegateAction = () => Console.WriteLine("Do something.");
myfoo.MethodCall();
myfoo.DelegateAction();
}
}
public class Foo
{
public void MethodCall()
{
if (this.DelegateAction != null)
{
this.DelegateAction();
}
}
public Action DelegateAction { get; set; }
}

Related

Is there a way to invoke a templated class on an anonymous type?

Here's some code to give the idea.
public class C<T> { }
public class X {
void M() {
var V = new { W = 1 };
var X = new C<V>(); // illegal
}
}
So V is a variable of an anonymous type and I would like to instantiate class C with V as its argument. This requires a type argument, which I cannot supply.
This questions is similar but the answer is not much help in my case: Why can't I instantiate a generic class inferring types from anonymous objects?
The question behind the question is that I'm trying to do what IEnumerable can do.
Should have made it clear: I would really prefer not to do this by manipulating object or Type because you lose the benefits of strong typing and Intellisense.
For anyone interested, the project that needs this is described here: http://www.andl.org/2016/07/andl-net-making-progress/.
You can use type inference if you have a factory method:
public class C<T>
{
public C(T t)
{
// ...
}
}
public static class Factory
{
public static C<T> Create<T>(T t)
{
return new C<T>(t);
}
}
public class Thing
{
void Foo()
{
var x = new { y = "z" };
//var thing = new C(x); - doesn't work, you need to specify the generic parameter
var thing = Factory.Create(x); // T is inferred here
}
}
You can't do that since V is instance of anonymous type, not a type name itself.
You can create this type dynamically (assuming parameterless constructor in C<>):
var X = typeof (C<>)
.MakeGenericType(V.GetType())
.GetConstructor(Type.EmptyTypes)
.Invoke(new object[0]);
You need a type, you can use pass object as a type.
Sample code:
public class C<T>
{
public T _t { get; set; }
public C(T t)
{
_t = t;
}
public void TestMethod()
{
Console.WriteLine(_t.ToString());
}
}
public class X
{
public void M()
{
var V = new { W = 1 };
var X = new C<object>(V); // everything is an object.
X.TestMethod();
}
}

How can I have conditional out parameters

The method DoSomething() does Create an Instance of MyClass but not everyone wants to know the MyClass-Object sometimes it also fits if you simply know if the action was successful.
This doesn't compile
public bool DoSomething(out Myclass myclass = null)
{
// Do something
}
A ref or out parameter cannot have a default value
Sure I could simply remove the out-Keyword but then I needed to assign any variable first, which is not my intention.
This could be a workaround, but i want bool to be the return type
public Myclass DoSomething() //returns null if not successful
{
// Do something
}
Does anyone know a nice Workaround for that?
Just by overloading:
public bool DoSomething()
{
myClass i;
return DoSomething(out i);
}
public bool DoSomething(out myClass myclass)
{
myclass = whatever;
return true;
}
And then call DoSomething()
You could wrap the parameter in a class.
class Arguments
{
public Argument () { Arg = null; }
public Myclass Arg { get; set; }
}
and then use it like:
Arguments args;
if (DoSomething (args))
{
// args.Arg is something
}
and define the function like:
bool DoSomething (Arguments args)
{
bool success = false;
if (someaction)
{
args.Arg = new Myclass;
success = true;
}
return success;
}
Alternative, and this is making me feel a bit dirty, use exceptions:-
Myclass DoSomething ()
{
if (someactionhasfailed)
{
throw new Exception ("Help");
}
return new Myclass;
}
If you do not want to overload the method, you can always create a new class like:
public class Response
{
public bool Success{get;set;}
public Myclass MyclassInstance {get;set;}
}
And the use it as a return parameter of your DoSomething() method with the following signature:
public Response DoSomething()
{
// Do something
}

Get reference to parameter inside a Lambda passed as a Func

Given the following set of classes:
public class MyClass
{
public int MyInt { get; set; }
}
public class ObjectProcessor
{
public int ProcessObject(MyClass myClass)
{
return myClass.MyInt ++;
}
}
public class Runner
{
public void Run()
{
var classToPass = new MyClass();
FuncExecutor.ExecuteAction<MyClass>(x => x.ProcessObject(classToPass));
}
}
public static class FuncExecutor
{
public static void ExecuteAction<T>(Expression<Func<ObjectProcessor, int>> expression)
{
// var func = expression.Compile(); ... does having an Expression help?
// How can I get a reference to 'classToPass' at this point?
// The 'classToPass' Type is known to be 'T', in this case 'MyClass'.
}
}
From within the ExecuteAction method, how can I get a reference to the classToPass instance that was passed in to ProcessObject?
EDIT: The comments have highlighted the complexity of trying to parse Expression Trees which could vary widely in their composition.
However, in this particular case there are two facts which cut down this variation considerably:
ProcessObject will only ever take a single parameter.
The parameter type is known in advance.
Code altered to express this.
To answer very specifically:
public class Runner
{
public void Run()
{
var classToPass = new MyClass();
classToPass.MyInt = 42;
FuncExecutor.ExecuteAction(x => x.ProcessObject(classToPass));
}
}
public class FuncExecutor
{
public static void ExecuteAction(Expression<Func<ObjectProcessor, int>> expression)
{
var lambdaExpression = (LambdaExpression)expression;
var methodCallExpression = (MethodCallExpression)lambdaExpression.Body;
var memberExpression = (MemberExpression)methodCallExpression.Arguments[0];
var constantExpression = (ConstantExpression)memberExpression.Expression;
var fieldInfo = (FieldInfo)memberExpression.Member;
var myClassReference = (MyClass) fieldInfo.GetValue(constantExpression.Value);
Console.WriteLine(myClassReference.MyInt); // prints "42"
}
}
Please note that when you pass the lambda to the ExecuteAction method, you capture a local variable reference (classToPass). The compiler will generate some code to handle that properly. More precisely, it will generate a type with a single member (a field) of type MyClass to hold the reference and use it from this point. That's why you'll get a MemberExpression in the argument expression list.
Since you can't directly manipulate this generated type, you can't just use the member expression Value property. But you can dynamically invoke the member accessor using the MemberInfo and the target reference (an instance of the compiler generated type).
I would not rely on this code.
You can read more about lambda related compiler generated code here, for example: http://thewalkingdev.blogspot.fr/2012/04/c-lambda-expressions-and-closures.html
The easiest way is to pass the instance as parameter and let ExecuteAction take care of calling the process method using that instance. To do this it is necessary to give your code a little bit of structure using a generic object processor interface:
public interface IObjectProcessor<T> {
public int ProcessObject(T instance);
}
public class MyClassProcessor : IObjectProcessor<MyClass> {
public int ProcessObject(MyClass myClass) {
return myClass.MyInt ++;
}
}
public class Runner {
public void Run() {
var classToPass = new MyClass();
var processor = new MyClassProcessor();
FuncExecutor.ExecuteAction<MyClass>(processor, classToPass);
}
}
public class FuncExecutor {
public static void ExecuteAction<T>(IObjectProcessor<T> processor, T obj) {
int result = processor.ProcessObject(obj);
}
}
This design could be a little annoying especially if your processor are "stateless" and if you really need a Func as parameter. In this case you can drop the interface and use static processors:
public class MyClassProcessor
public static int ProcessObject(MyClass myClass) {
return myClass.MyInt ++;
}
}
public class Runner {
public void Run() {
var classToPass = new MyClass();
FuncExecutor.ExecuteAction<MyClass>(MyClassProcessor.ProcessObject, classToPass);
}
}
public class FuncExecutor {
public static void ExecuteAction<T>(Func<T, int> process, T obj) {
int result = process(obj);
}
}

pass callback to class

I have a class in which I would like to store a function call. This function call can be invoked by the class but set by the parent class. I would like to externally supply the call to be made, including any parameters.
Something like...
public class TestDelegate
{
public TestDelegate()
{
TestClass tc = new TestClass(DoSomething("blabla", 123, null));
}
private void DoSomething(string aString, int anInt, object somethingElse)
{
...
}
}
public class TestClass
{
public TestClass(delegate method)
{
this.MethodToCall = method;
this.MethodToCall.Execute();
}
public delegate MethodToCall { get; set; }
}
When the TestClass class is initialized it will call the DoSomething method of the parent class with the specified parameters. I should also mention that I do not want to require the same method signature for the method called. Meaning not always (string, int, object)
Use the Action delegate type and create an instance of this from a closure:
public class TestClass
{
public TestClass(Action method)
{
MethodToCall = method;
method();
}
public Action MethodToCall { get; set; }
}
public class TestDelegate
{
public TestDelegate()
{
// Uses lambda syntax to create a closure that will be represented in
// a delegate object and passed to the TestClass constructor.
TestClass tc = new TestClass(() => DoSomething("blabla", 123, null));
}
private void DoSomething(string aString, int anInt, object somethingElse)
{
// ...
}
}
delegate isn't the name of a type - it's a keyword used to declare delegate types, and also anonymous methods.
I suspect you actually want a specific type of delegate, such as Action, which is a delegate with no parameters and a void return type. You'll then need to change your calling code as well - because currently you're calling DoSomething before you call the constructor. Sample:
public class TestDelegate
{
public TestDelegate()
{
TestClass tc = new TestClass(() => DoSomething("blabla", 123, null));
}
private void DoSomething(string aString, int anInt, object somethingElse)
{
...
}
}
public class TestClass
{
public TestClass(Action method)
{
this.MethodToCall = method;
this.MethodToCall.Invoke();
}
// Do you really need this to be writable?
public Action MethodToCall { get; set; }
}

Closures and reference setting

I think I have a fundamental misunderstanding here. Why does the test fail?
public static class ObjectExtensions
{
public static Action To<T>(this T newValue, T oldValue) where T : class
{
return () => oldValue = newValue;
}
}
public static class Assign
{
public static T TheValue<T>(T theValue)
{
return theValue;
}
}
public class Tests
{
public void Test()
{
var a = new TestType { Name = "a" };
var b = "b";
Assign.TheValue(b).To(a.Name)();
Assert.That(a.Name == "b"); //fails (a.Name == "a")
}
}
public class TestType { public string Name {get;set;} }
It fails because the arguments to To are passed by value.
Just because oldValue is set to "b" doesn't mean that a.Name will be changed at all. In the call To(a.Name), the expression a.Name is evaluated to a string reference, and that reference is passed to the method by value.
That's basic parameter passing in C#. Just using a closure doesn't change that.
What you can do is change the To method like this:
public static Action To<T>(this T newValue, Action<T> setter) where T : class
{
return () => setter(newValue);
}
then change the call to:
Assign.TheValue(b).To(x => a.Name = x)();
Put another way,
var a = new TestType { Name = "a" };
Assign.TheValue(b).To(a.Name)();
is equivalent to
Assign.TheValue(b).To("a")();
just like
int x = 5;
Convert.ToDecimal(x);
is equivalent to
Convert.ToDecimal(5);

Categories

Resources