I have a simple Screen class in C# that has a bunch of events (with corresponding delegates) like the FadeOutEvent.
I want to port my library to Java, and I find that the mechanism for events/delegates is really cludgey. Specifically, I cannot easily write code like:
if (someVar == someVal) {
this.FadeOutComplete += () => {
this.ShowScreen(new SomeScreen());
};
} else {
this.FadeOutComplete += () => {
this.ShowScreen(new SomeOtherScreen());
};
}
For all you Java-only guys, essentially, what I'm whinging about is the inability to reassign the event-handling method in the current class to something else dynamically, without creating new classes; it seems that if I use interfaces, the current class must implement the interface, and I can't change the code called later.
In C#, it's common that you have code that:
In a constructor / early on, assign some event handler code to an event
Later during execution, remove that code completely
Often, change that original handler to different handler code
Strategy pattern can solve this (and does), albeit that I need extra classes and interfaces to do it; in C#, it's just a delcarative event/delegate and I'm done.
Is there a way to do this without inner/anonymous classes?
Edit: I just saw this SO question, which might help.
Most of the time, it's done the other way round:
this.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if (someVar == someVal) {
showSomeScreen();
}
else {
showSomeOtherScreen();
}
}
});
But you could do something similar to your C# code by delegating to two other objects:
private Runnable delegate;
// ...
this.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
delegate.run();
}
});
// ...
if (someVar == someVal) {
this.delegate = new Runnable() {
#Override
public void run() {
showSomeScreen();
}
};
}
else {
this.delegate = new Runnable() {
#Override
public void run() {
showSomeOtherScreen();
}
};
}
Delegates were proposed by Microsoft for Java a long long time ago, and were refused by Sun. I don't remember if anonymous inner classes already existed at that time or if they were chosen as the alternative.
With lambdas in JDK 1.8 / Java 8:
private Runnable delegate;
public void delegateTest() {
// ...
this.addActionListener(e -> delegate.run());
// ...
if (someVar == someVal) {
this.delegate = () -> showSomeScreen();
}
else {
// or like this:
this.delegate = this::showSomeOtherScreen;
}
}
private void showSomeOtherScreen() {
}
private void showSomeScreen() {
}
Related
I have a class which has some events. At present, I decide to shift towards "Observables" since the benefits they propose. To reach this goal, I introduced an Observable property to be replaced with one of the events. Next, I made the event "private" to restrict its accessibility from out of the class. The event is invoked inside the class with a function when it is needed. However, I think It may be a better way to do this job. What is the proper practice? By the way, I am a novice in "System.Reactive," so if I have a misunderstanding with the concept, please clarify the matter. My code is below:
public class MyClass
{
public MyClass()
{
InformationSenderObservable=Observable.FromEventPattern<SolutionEventArg>(ev =>InformationSender += ev, ev => InformationSender -= ev);
}
private event EventHandler<SolutionEventArg> InformationSender;
public IObservable<EventPattern<SolutionEventArg>> InformationSenderObservable { get; }
internal void DoSomething()
{
// long calculation
SendInformation();
}
private void SendInformation()
{
InformationSender?.Invoke(this,new SolutionEventArg()
{
InfoProxyData = GetDetailsForBestCompressedData(),
ParallelProcess = parallelProcessing
});
}
}
Thanks to Theodor Zoulias, I finally understood how I could better handle my class. I used ISubject<T> instead of events in my class to send information from my class to another class subscribing to the ISubject<T>.
public class MyClass
{
public MyClass()
{
InformationSenderObservable=new Subject<SolutionEventArg>();
}
public ISubject<SolutionEventArg> InformationSenderObservable { get; }
internal void DoSomething()
{
// long calculation
SendInformation();
}
private void SendInformation()
{
try
{
InformationSenderObservable.OnNext(new SolutionEventArg()
{
InfoProxyData = GetDetailsForBestCompressedData(),
ParallelProcess = parallelProcessing
});
}
catch (Exception e)
{
InformationSenderObservable.OnError(e);
}
}
}
ISubject<T> implements both IObservable<T> and IObserver<T> simultaneously.
This would be the first time I'd use delegates in c# so please bear with me. I've read a lot about them but never thought of how/why to use this construct until now.
I have some code that looks like this:
public class DoWork()
{
public MethodWorkA(List<long> TheList) {}
public void MethodWork1(parameters) {}
public void MethodWork2(parameters) {}
}
I call MethodWorkA from a method outside the class and MethodWorkA calls MethodWork 1 and 2. When I call methodA, I'd like to pass some sort of parameter so that sometimes it just does MethodWork1 and sometimes it does both MethodWork1 and MethodWork2.
So when I call the call it looks like this:
DoWork MyClass = new DoWork();
MyClass.MethodA...
Where does the delegate syntax fit in this?
Thanks.
public void MethodWorkA(Action<ParamType1, ParamType2> method) {
method(...);
}
You can call it using method group conversion:
MethodWorkA(someInstance.Method1);
You can also create a multicast delegate that calls two methods:
MethodWorkA(someInstance.Method1 + someInstance.Method2);
For what you described, you don't need delegates.
Just do something like this:
public class DoWork
{
public void MethodWorkA(List<long> theList, bool both)
{
if (both)
{
MethodWork1(1);
MethodWork2(1);
}
else MethodWork1(1);
}
public void MethodWork1(int parameters) { }
public void MethodWork2(int parameters) { }
}
If you're just experimenting with delegates, here goes:
public partial class Form1 : Form
{
Func<string, string> doThis;
public Form1()
{
InitializeComponent();
Shown += Form1_Shown;
}
void Form1_Shown(object sender, EventArgs e)
{
doThis = do1;
Text = doThis("a");
doThis = do2;
Text = doThis("a");
}
string do1(string s)
{
MessageBox.Show(s);
return "1";
}
string do2(string s)
{
MessageBox.Show(s);
return "2";
}
}
Considering that all methods are inside the same class, and you call MethodWorkA function using an instance of the class, I honestly, don't see any reason in using Action<T> or delegate, as is I understood your question.
When I call methodA, I'd like to pass some sort of parameter so that
sometimes it just does MethodWork1 and sometimes it does both
MethodWork1 and MethodWork2.
Why do not just pass a simple parameter to MethodWorkA, like
public class DoWork()
{
public enum ExecutionSequence {CallMethod1, CallMethod2, CallBoth};
public MethodWorkA(List<long> TheList, ExecutionSequence exec)
{
if(exec == ExecutionSequence.CallMethod1)
MethodWork1(..);
else if(exec == ExecutionSequence.CallMethod2)
MethodWork2(..);
else if(exec == ExecutionSequence.Both)
{
MethodWork1(..);
MethodWork2(..);
}
}
public void MethodWork1(parameters) {}
public void MethodWork2(parameters) {}
}
Much simplier and understandable for your class consumer.
If this is not what you want, please explain.
EDIT
Just to give you an idea what you can do:
Example:
public class Executor {
public void MainMethod(long parameter, IEnumerable<Action> functionsToCall) {
foreach(Action action in functionsToCall) {
action();
}
}
}
and in the code
void Main()
{
Executor exec = new Executor();
exec.MainMethod(10, new List<Action>{()=>{Console.WriteLine("Method1");},
()=>{Console.WriteLine("Method2");}
});
}
The output will be
Method1
Method2
In this way you, for example, can push into the collection only functions you want to execute. Sure, in this case, the decision logic (which functions have to be executed) is determined outside of the call.
I have a boolean function which is used in the decision-making of many other functions. And every time, the user is either given a message box or allowed to proceed, depending on the return value of that function. So my pseudo-code might look like this:
private bool IsConsented()
{
//some business logic
}
private void NotReal()
{
if (IsConsented())
{
//call function A
}
else
{
MessageBox.Show("Need consent first.");
}
}
private void NotReal2()
{
if (IsConsented())
{
//call function B
}
else
{
MessageBox.Show("Need consent first.");
}
}
I am looking for a simpler way to do this, rather than hard-coding that if-else logic into every single function of mine. I'd like to be able to have a function like:
private void CheckConsent(function FunctionPointer)
{
if (IsConsented())
{
//call the function
FunctionPointer();
}
else
{
MessageBox.Show("Need consent first.");
}
}
So that I can just pass a pointer to a function. I have a real suspicion that this has to do with delegates, but I don't know the syntax, and I don't understand how to pass parameters around using delegates.
You need to declare the delegate (or use a built-in one, such as Action):
private void CheckConsent(Action action)
{
if (IsConsented())
{
action();
}
else
{
MessageBox.Show("Need consent first.");
}
}
You could then do:
private void NotReal()
{
this.CheckConsent( () =>
{
// Do "NotReal" work here...
});
}
Reed Copsey way of doing is clean one. It uses the Action delegate already defined along with lambda expression. But if you are not comfortable with that here is the old way of doing .
private delegate void realDelegate();
realDelegate d = new realDelegate(NotReal);
You can now call
private void CheckConsent(realDelegate d)
{
if(d !=null)
d();
}
I would like to make a delegate available to an entire class. The point of this is to allow a called method from an external class' backgroundWorker to continually report back through all of it's methods (ExternalClass.Run(); calls ExternalClass.Method2(); ExternalClass.Method3(); etc and they all need to send several progress reports. It seems inefficient to have to continually pass the delegate.
I've tried initializing an instance of the delegate globally and setting it to equal the passed instance in Run(); for each method to then have available to it but I am given an error that a null object cannot be implicitly converted.
thanks!
I cannot show the code I am working with as I do not currently have it with me (it's on my laptop) but I will try to better explain now. PSEUDO-CODE:
class form1 : form {
backgroundWorker_doWork()
{
Class2.Run();
}
backgroundWorker_OnProgressChange()
{
// do this
}
}
class class2{
Run(){
OtherMethod();ThirdMethod();
}
OtherMethod(){ //need to call backgroundWorker.ReportProcess(int, string)}
ThirdMethod(){ //need to call backgroundWorker.ReportProcess(int, string)}
}
I really don't want to have to pass it every time is the point, i'd like to somehow pass it to class2
You should show your code that isn't working and the exact error message. It should be fine - here's an example:
using System;
class Demo
{
private readonly Action action;
public Demo(Action action)
{
this.action = action;
}
public void FirstMethod()
{
Console.WriteLine("In first method");
action();
}
public void SecondMethod()
{
Console.WriteLine("In second method");
action();
}
}
class Test
{
static void Main()
{
Demo demo = new Demo(() => Console.WriteLine("Action called"));
demo.FirstMethod();
demo.SecondMethod();
}
}
You can use the InvokeMethod function from a backgroundWorker to allow the worker to execute any delegate, example below (also waits for the invoke to finish, which you may not need):
BackgroundWorker Function (C++.net)
BackgroundWorkerFunction()
{
::IAsyncResult ^ThreadResult;
SetTileCount_Delegate ^SetCountDel = gcnew SetTileCount_Delegate(this, &PartDetail::SetTileCount_Function);
//RecordingContainer is the class I am invoking into
ThreadResult = this->RecordingContainer->BeginInvoke(
SetCountDel, ThisTest->RecordingsCache->Count);
WaitForInvokeTimeOutOrCompletion(ThreadResult);
}
System::Void WaitForInvokeTimeOutOrCompletion(IAsyncResult ^ThreadResult)
{
if(ThreadResult == nullptr) return;
long SleepTotal = 0;
long SleepInterval = 100;
while ((SleepTotal <= 2000) && !ThreadResult->IsCompleted)
{
ThreadResult->AsyncWaitHandle->WaitOne(SleepInterval, false);
SleepTotal += SleepInterval;
}
}
Given:
interface I
{
}
class B: I
{
}
class C: I
{
}
class A
{
public void Method(B arg)
{
}
public void Method(C arg)
{
}
public void Method(I arg)
{
// THIS is the method I want to simplify.
if (I is B)
{
this.Method(arg as B);
}
else if (I is C)
{
this.Method(arg as C);
}
}
}
I know that there are better ways to design this type of interactions, but because of
details which would take too long to explain this is not possible.
Since this pattern will be duplicated MANY times, I would like to replace the
conditional logic with a generic implementation which I could use just one line.
I can't see a simple way to implement this generic method/class, but my instincts tell me it should be possible.
Any help would be appreciated.
I would put the method inside the interface and then let polymorphism decide which method to call
interface I
{
void Method();
}
class B : I
{
public void Method() { /* previously A.Method(B) */}
}
class C : I
{
public void Method() { /* previously A.Method(C) */ }
}
class A
{
public void Method(I obj)
{
obj.Method();
}
}
Now when you need to add a new class, you only need to implement I.Method. You don't need to touch A.Method.
What you want is double dispatch, and visitor pattern in particular.
This is kinda ugly but it gets the job done:
public void Method(B arg)
{
if (arg == null) return;
...
}
public void Method(C arg)
{
if (arg == null) return;
...
}
public void Method(I arg)
{
this.Method(arg as B);
this.Method(arg as C);
}
I don't think I would do it this way, though. It actually hurts looking at that. I'm sorry I forced you all to look at this as well.
interface I
{
}
class B : I
{
}
class C : I
{
}
class A
{
public void Method(B arg)
{
Console.WriteLine("I'm in B");
}
public void Method(C arg)
{
Console.WriteLine("I'm in C");
}
public void Method(I arg)
{
Type type = arg.GetType();
MethodInfo method = typeof(A).GetMethod("Method", new Type[] { type });
method.Invoke(this, new I[] { arg });
}
}
It doesn't exist in a convenient form withing C# - see here for an idea based on F#'s pattern matching, that does exactly what you want. You can do some things with reflection to select the overload at runtime, but that will be very slow, and has severe issues if anything satisfies both overloads. If you had a return value you could use the conditional operator;
return (I is B) ? Method((B)I) : ((I is C) ? Method((C)I) : 0);
Again - not pretty.
Easy. In Visual Basic I do this all the time using CallByName.
Sub MethodBase(value as Object)
CallByName(Me, "RealMethod", CallType.Method, value)
This will call the overload of RealMethod that most closely matches the runtime type of value.
I'm sure you can use CallByName from C# by importing Microsoft.VisualBasic.Interaction or by creating your own version using reflection.