I created a library that handles database access. I recently added transaction handling; however, I came across a small issue. To outline this, I wrote this sample for demonstration purposes:
class Program
{
static void Main(string[] args)
{
String data = null;
DoAction(ref data, () =>
{
Console.WriteLine(data);
});
Console.ReadLine();
}
private static void DoAction(ref String data, Action action)
{
if (data == null)
data = "Initialized Data";
action();
}
}
I get "Access to modified closure" underline on the following code line for the 'data' variable:
Console.WriteLine(data);
I understand that the modification of the ref data variable can cause issues (e.g. when running foreach loops). However, in the following case, I don't see this to happen.
Here is another version with a loop changing the variable further - the output is as expected:
class Program
{
static void Main(string[] args)
{
String data = null;
for (var i = 0; i < 10; i++)
DoAction(ref data, () =>
{
Console.WriteLine(data);
});
Console.ReadLine();
}
private static void DoAction(ref String data, Action action)
{
if (data == null)
data = "Initialized Data";
else
data += "|";
action();
}
}
ReSharper offers me to create a local variable, but I explicitly want to use the created string from the DoAction() method. If I would accept ReSharpers approach, it actually would break the code. Is there any other way to solve this problem? I'd like to use this Action approach, but I don't want ReSharper to complain about it either (and possibly not disable ReSharpers inspection).
Any suggestions?
I would suggest avoid using a ref parameter for this in the first place - it seems needlessly complicated to me. I'd rewrite DoAction as:
static string DoAction(string data, Action<string> action)
{
data = data == null ? "Initialized Data" : data + "|";
action(data);
return data;
}
Then you can have:
data = DoAction(data, Console.WriteLine);
or if you want to use a lambda expression:
data = DoAction(data, txt => Console.WriteLine(txt));
You can make DoAction a void method if you don't actually need the result afterwards. (It's not clear why you need the result to be returned and a delegate to execute in DoAction, but presumably that makes more sense in your wider context.)
In case you feel certain that the warning is not appropriate, there is the InstantHandleAttribute which is documented as:
Tells code analysis engine if the parameter is completely handled
when the invoked method is on stack. If the parameter is a delegate,
indicates that delegate is executed while the method is executed.
If the parameter is an enumerable, indicates that it is enumerated
while the method is executed.
I think is exactly what you want.
You can get the attribute from the JetBrains.Annotations package or alternatively as copy-paste from ReSharper options.
Related
I'm generating a random number from 1-1000. I have 200 functions named function1, function4, function 10, function 11, etc. What I would like to do is execute a specific function depending on if the number generated requires a function, and ignore it if not.
My first thought was to create an int[] containing all of the values that would trigger a function, and if the int[] contains the random number to use if statements to figure out what the number is. I'm concerned that it must be a really crude solution to an easy problem though.
I know the "best way" to do something is subjective, but is there a better way to accomplish this?
UPDATE: As per comments, I should probably have started out by pointing out that doing this for 200 functions is probably a good sign that there is some serious issue in your design. This is probably an XY question where you are trying to solve a problem in some crazy way and asking about your intended solution instead of asking about the problem itself.
That said I'll leave the original answer because it's still good advice when mapping a reasonable amount of function calls that can/will change during the life cylce of your app or dynamically as the code runs.
I won't get into why you are doing this, but I'll try to at least point you in the right direction so this doesn't become a complete nightmare when you need to modify/expand behavior:
You can map numbers to function calls using delegates and a dictionary. Assuming your functions take no arguments and return void you'd do:
var functionsMap = new Dictionary<int, Action>();
//map functions
var r = getSomeRandomNumber();
if (functions.TryGetValue(r), out var a)
a(); //invoke function
Mapping functions is simply adding keys and values:
functionsMap.Add(1, () => function1());
functionsMap.Add(3, () => function3());
//etc.
If your functions take arguments or return values, you'd use the adequate delegate: Action<T>, Func<T1, T2> etc.
You can use reflection to invoke appropriate method:
Type exampleType = exampleObject.GetType();
MethodInfo exampleMethod = exampleType.GetMethod(methodName);
exampleMethod.Invoke(this, null);
Where methodName can be created using your random number.
Without commenting on the wisdom of having 200 functions named the way yours are, you can use reflection to determine whether a given functionX() exists, like so:
public void ExecuteDynamicMethod(int number)
{
// Modify these two lines with your app's dll/exe and class type:
Assembly assembly = Assembly.LoadFile("...Assembly1.dll");
Type type = assembly.GetType("YourClassType");
if (type != null)
{
MethodInfo methodInfo = type.GetMethod("function" + number);
if (methodInfo != null)
{
object classInstance = Activator.CreateInstance(type, null);
methodInfo.Invoke(classInstance, null); // null = "no function arguments"
}
}
}
This can then be called for a given value like
ExecuteDynamicMethod(14);
See this SO answer for the inspiration behind this.
Reflection can be used for this purpose. I want to give and keep below example for not only the objective of the question but also for future reference. Also, of course that many function is not good but below code shows the approach that can work with many functions if they have similar name (like starting with "function" keyword).
Assume below is Methods.cs
using System;
using System.Reflection;
namespace YourMethodNamespace
{
public class YourMethodClass
{
public void function1()
{
Console.WriteLine("Function-1");
}
public void function2()
{
Console.WriteLine("Function-2");
}
...
public void function200()
{
Console.WriteLine("Function-200");
}
public static void invokeMethodsDynamically(int randomNumber){
Type yourClassType = typeof(YourMethodClass);
ConstructorInfo yourClassConstructorInfo = yourClassType.GetConstructor(Type.EmptyTypes);
object yourClassObject = yourClassConstructorInfo.Invoke(new object[]{});
//If the constructor has parameters, then we can pass them by this way. Like below;
/*ConstructorInfo yourClassConstructorInfo = yourClassType.GetConstructor(new[]{typeof(int)});
object yourClassObject = yourClassConstructorInfo.Invoke(new object[]{3});
*/
MethodInfo[] methodInfoArr = yourClassType.GetMethods();
foreach(MethodInfo methodInfo in methodInfoArr){
if(methodInfo.Name == "function" + randomNumber){
methodInfo.Invoke(yourClassObject, null);
}
}
}
}
}
Let's say below is Program.cs
using System;
using YourMethodNamespace;
namespace YourProgramNamespace
{
public class YourProgramClass
{
public static void Main()
{
Random random = new Random();
int randomNumber = random.Next(1, 201);
//If Methods.cs is in another Assembly
/*string pathToDllAssembly = #"Domain.dll";
Assembly dllAssembly = Assembly.LoadFrom(pathToDllAssembly);
Type methodsClassType = dllAssembly.GetType("YourMethodNamespace.YourMethodClass");
ConstructorInfo methodClassConstructorInfo = methodsClassType.GetConstructor(Type.EmptyTypes);
object methodsClassObject = methodClassConstructorInfo.Invoke(new object[]{});
MethodInfo methodInfo = methodsClassType.GetMethod("invokeMethodsDynamically");
methodInfo.Invoke(methodsClassObject, new object[]{randomNumber});
*/
YourMethodClass.invokeMethodsDynamically(randomNumber, null);
}
}
}
Also for testing and observing, below link can be used.
https://repl.it/#erdsavasci/ReflectionTest
I'm trying to write a code analysis rule with roslyn.
Basically, I have to check whether an each of arguments which a Microsoft.Practices.Prism.Commands.DelegateCommand() is created is wrapped in try catch or not.
The main idea is collect all ObjectCreationExpressionSyntax objects of DelegateCommand class and check each constructor's argument if the first StatementSyntax is TryStatementSyntax or not.
Can you help me with getting all StatementSyntax from ArgumentSyntax ? Or may be you have an another approach ?
public IEnumerable<IdentifierInfo> Collect(SyntaxNode rootNode, SemanticModel semanticModel)
{
ObjectCreationExpressionSyntax[] objCreation = rootNode
.DescendantNodes()
.OfType<ObjectCreationExpressionSyntax>()
.Where(c=>(c.Type as IdentifierNameSyntax)?.Identifier.Value.ToString() == "DelegateCommand")
.ToArray();
foreach (var obj in objCreation)
{
var args = obj.ArgumentList.Arguments;
foreach (ArgumentSyntax arg in args)
{
var expession = arg.Expression;
var symbol = semanticModel.GetSymbolInfo(expession).Symbol as IMethodSymbol;
}
}
}
Bellow you can find what I actually compile for searching through:
public class Program
{
public delegate void MyDelegate();
public static void DelegateMethod() { try { } catch { } }
public static void Main(string[] args)
{
DelegateCommand del1 = new DelegateCommand(() => {try{}catch{}});
DelegateCommand del2 = new DelegateCommand(new Action(() => { }));
DelegateCommand del3 = new DelegateCommand(DelegateMethod);
var barInit = (Action)(DelegateMethod);
DelegateCommand del4 = new DelegateCommand(barInit);
ICommand test;
test = new Microsoft.Practices.Prism.Commands.DelegateCommand(() => { });
}
}
You start in a good way, but to handle it completely, its required more work.
Lets see in your example what we have
(The screenshot is from LINQ debugging feature from OzCode)
Here what I wrote is
var argsExpr = objCreation.Select(o => o.ArgumentList.Arguments.First())
As you can see in the right side of the window, we have a three types of syntax nodes in the arguments, so we don't have a general way to handle them all.
You have two ways to handle it.
Write method that get SyntaxNode and according to its type, check if the first statement is a try\catch statement
Write SyntaxWalker and visit relevant methods, and there, check if the first statement is a try\catch statement
For example to handle the first case which is ParenthesizedLambdaExpressionSyntax you need to write something like this (or by yourself or by overriding the appropriate Visit method of the SyntaxWalker)
public static bool IsTryStatement(ParenthesizedLambdaExpressionSyntax node)
{
return ((BlockSyntax) node.Body).Statements.First() is TryStatementSyntax;
}
This is just an example. In your real code you need to handle all cases.
For the IdentifierNameSyntax you need to get the method symbol first:
semanticModel.GetSymbolInfo(identifier).Symbol
Then you need to get the syntax node from DeclaringSyntaxReferences and use span, or you can use location of the symbol or any other way (ConstructFrom maybe).
Is it possible to make a variable, and assign a line of code to it, such as:
ButtonClicked = (MessageBox.Show("Hello, World!"));
... so when I use the variable, it will execute the line of code.
You could assign it to an Action like this:
var ButtonClicked = new Action(() => MessageBox.Show("hi"));
Then call it:
ButtonClicked();
For completeness (in regards to the various comments)...
As Erik stated, you could execute multiple lines of code:
var ButtonClicked = new Action(() =>
{
MessageBox.Show("hi");
MessageBox.Show("something else"); // something more useful than another popup ;)
});
As Tim stated, you could omit the Action keyword
Action ButtonClicked = () => MessageBox.Show("hi");
Action ButtonClicked = () =>
{
// multiple lines of code
};
To address KRyan's comment, regarding the empty parentheses, that represents the list of parameters you want to be able to send to the Action (in this case, none).
If, for instance, you wanted to specify the message to show, you could add "message" as a parameter (note that I changed Action to Action<string> in order to specify a single string parameter):
Action<string> ButtonClicked = (message) => MessageBox.Show(message);
ButtonClicked("hello world!");
In your case, you want to use a delegate.
Let's see how a delegate works and how we can get to an easier form by understanding its concept:
// Create a normal function
void OnButtonClick()
{
MessageBox.Show("Hello World!");
}
// Now we create a delegate called ButtonClick
delegate void ButtonClick();
You see, the delegate takes the form of a normal function but without any arguments (It could take any amount of arguments just like any other method, but for the sake of simplicity, it doesn't).
Now, let's use what we have; we will define the delegate just as we define any other variable:
ButtonClick ButtonClicked = new ButtonClick(OnButtonClick);
We basically created a new variable called ButtonClicked, that has a type of ButtonClick (which is a delegate) and that when used, will execute the method in the OnButtonClick() method.
To use it we simply call: ButtonClicked();
So the whole code would be:
delegate void ButtonClick();
void OnButtonClick()
{
MessageBox.Show("Hello World!");
}
void Foo()
{
ButtonClick ButtonClicked = new ButtonClick(OnButtonClick);
ButtonClicked(); // Execute the function.
}
From here, we can move to lambda expressions and see how they could be useful in your situation:
There are many delegates already defined by .NET libraries, with some like Action, which do not accept any parameter and does no return a value. It is defined as public delegate void Action();
You can always use it to your needs instead of the need of defining a new delegate every time. In the previous context for example, you could had just written
Action ButtonClicked = new Action(OnButtonClick);
ButtonClicked();
which would had done the same.
Now that you saw different ways of how to use delegates, let's use our first lambda expression. Lambda expressions are anonymous functions; so, they are normal functions but without a name. They are of those forms:
x => DoSomethingWithX(x);
(x) => DoSomethingWithX(x);
(x,y) => DoSometingWithXY(x,y);
() => Console.WriteLine("I do not have parameters!");
In our case, we do not have any parameters so we will use the last expression. We can use this just as the OnButtonClick function, but we get the advantage of not having a named function. We can instead do something like this:
Action ButtonClicked = new Action( () => MessageBox.Show("Hello World!") );
or even easier,
Action ButtonClicked = () => MessageBox.Show("Hello World!");
then simply call ButtonClicked(); Of course you can also have multi-lines of code, but I do not want to confuse you more. It would look like this though:
Action ButtonClicked = () =>
{
MessageBox.Show("Hello World!");
};
ButtonClicked();
You could also play around, for example, you can execute a function like this:
new Action(() => MessageBox.Show("Hello World!"))();
Sorry for the long post, hope it was not too confusing :)
EDIT: I forgot to mention that an alternate form which, even though not often used, could make lambda expressions easier to understand:
new Action(delegate() {
Console.WriteLine("I am parameterless");
})();
Also, using generics:
// Defines a delegate that has one parameter of type string. You could pass as many parameters as you want.
new Action<string>(delegate(string x) {
Console.WriteLine(x);
})("I am a string parameter!");
In turn you could use lambda expressions, but you do not need (but might in some cases) to define the type of the parameter, for example, the code above could simply be written as:
new Action<string>(x => {
Console.WriteLine(x);
})("I am a string parameter!");
or:
new Action<string>(x => Console.WriteLine(x))("I am a string parameter!");
EDIT2:
Action<string> is a representation of public void delegate Action(string obj);
Action<string,string> is a representation of public void delegate Action(string obj, string obj2);
In general, Action<T> is a representation of public void delegate Action<T>(T obj);
EDIT3:
I know the post has been here for a while, but I think this is really cool to not mention:
You can do this, which is mostly related to your question:
dynamic aFunction = (Func<string, DialogResult>)MessageBox.Show;
aFunction("Hello, world!");
or simply:
Func<string, DialogResult> aFunction = MessageBox.Show;
aFunction("Hello, world!");
The Lazy class is specifically designed to represent a value that won't be computed until you ask for it. You construct it by providing a method that defines how it should be constructed, but it will handle executing that method no more than once (even in the face of multiple threads requesting the value) and simply returning the already constructed value for any additional requests:
var foo = new Lazy<DialogResult>(()=>MessageBox.Show("Hello, World!"));
var result = foo.Value;
The way I'm reading your question, this is in the context of GUI controls?
If this is in WPF, take a look at the "right" way to handle commands from controls:
http://msdn.microsoft.com/en-us/library/ms752308(v=vs.110).aspx
...but that can be a pain and overkill. For a simpler general case, you might be looking for an event handler, like:
myButton.Click += (o, e) => MessageBox.Show("Hello, World!");
That event handler can be handled a variety of ways. The above example uses an anonymous function, but you could also do:
Action<object, RoutedEventArgs> sayHello = (o, e) => MessageBox.Show("Hello, World");
myButton.Click += new RoutedEventHandler(sayHello);
...just like you were asking, with a function (or here, "Action", since it returns void) assigned as a variable.
You can assign C# code to a variable, compiling it at runtime and run the code:
Write your code:
// Assign C# code to the code variable.
string code = #"
using System;
namespace First
{
public class Program
{
public static void Main()
{
" +
"Console.WriteLine(\"Hello, world!\");"
+ #"
}
}
}
";
Create the provider and parameters of the compiler:
CSharpCodeProvider provider = new CSharpCodeProvider();
CompilerParameters parameters = new CompilerParameters();
Define parameters of the compiler:
// Reference to System.Drawing library
parameters.ReferencedAssemblies.Add("System.Drawing.dll");
// True - memory generation, false - external file generation
parameters.GenerateInMemory = true;
// True - exe file generation, false - dll file generation
parameters.GenerateExecutable = true;
Compile assembly:
CompilerResults results = provider.CompileAssemblyFromSource(parameters, code);
Check errors:
if (results.Errors.HasErrors)
{
StringBuilder sb = new StringBuilder();
foreach (CompilerError error in results.Errors)
{
sb.AppendLine(String.Format("Error ({0}): {1}", error.ErrorNumber, error.ErrorText));
}
throw new InvalidOperationException(sb.ToString());
}
Get assembly, type and the Main method:
Assembly assembly = results.CompiledAssembly;
Type program = assembly.GetType("First.Program");
MethodInfo main = program.GetMethod("Main");
Run it:
main.Invoke(null, null);
Reference:
http://www.codeproject.com/Tips/715891/Compiling-Csharp-Code-at-Runtime
Evening guys,
This may seem like a stupid question but im having some issues figuring out where i should be placing my user input verification checks. I have checks, for the following:
file exists
Correct extension
Access to the file
Input in 2 NumericUpDown controls
One numericUpDown is always greater than the other.
Assignment to static properties.
Im assuming each one of these should at least be a single method but i then have a single method which has a large number of lines which solely check the result of the method calls to the list above. ie
public void VerifyData()
{
if(VerifyNumber1OnTheList != true)
{
LogError("The file specified is incorrect")
return;
}
if(VerifyNumber2OnTheList != ......
Any suggestions on how i should actually be laying this out would be appreciated.
Thanks
Putting a series of validation methods is ok.
This is user input, so you're doing defensive programming here, not looking for exceptional errors. It seems like you'd want to know why the user input is bad. If so, a simple approach is to use a collecting object to visit each validation method
public void VerifyData(ValidationErrors errors)
{
ValidateFileExists(errors);
ValidateExtension(errors);
ValidateFileAccess(errors);
...
}
private void ValidateFileExists(ValidationErrors errors)
{
if(!File.Exists...)
{
errors.Add("File does not exists.");
}
}
public void CallingMethod(UserInput input)
{
_dataToVerify = input;
var errors = new ValidationErrors();
VerifyData(errors);
if(errors.Count > 0)
ShowErrors(errors);
else
ShowSuccess();
}
I just put the data in an instance variable for purposes of simplicity, you could pass that into your validation method. This approach is simple but allows you to tell the user something about the input and how to correct it.
All right here is a quick sample I wrote up for you. Architecture obviously is your choice here. Modify as needed. I believe this should be a great jumping off point for you.
Cheers
Matt
using System.Collections.Generic;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
//This would simulate the event handler that calls your validation event
List<string> errorList = Validation.VerifyData();
if (errorList.Count != 0)
{
ErrorHandler.HandleError(errorList);
return;
}
//Do stuff if validation actually passed here.
}
}
public static class Validation
{
public static List<string> VerifyData()
{
List<string> errorList = new List<string>();
//File exists
if (true)
errorList.Add("File doesn't exist.");
//File has correct extension
if (true)
errorList.Add("File doesn't exist.");
//Has access to the file
if (true)
errorList.Add("File doesn't exist.");
//INput in 2 NumericUpDownControls
if (true)
errorList.Add("File doesn't exist.");
//One NumericUpDown is always greater than the other
if (true)
errorList.Add("File doesn't exist.");
//Assignment to static properties
if (true)
errorList.Add("File doesn't exist.");
return errorList;
}
}
public static class ErrorHandler
{
public static void HandleError(List<string> errorMessageList )
{
//Display your message here. This could return a dialog result as well for further processing.
}
}
}
Your method above seems like a perfectly fine way of laying out your code.
My only change would be in how you handle your checking. Use well-named methods rather than booleans during your check:
public void VerifyData()
{
if(FileExists())
{
LogError("The file specified is incorrect")
return;
}
if(CorrectExtension())
What's a callback and how is it implemented in C#?
I just met you,
And this is crazy,
But here's my number (delegate),
So if something happens (event),
Call me, maybe (callback)?
In computer programming, a callback is executable code that is passed as an argument to other code.
—Wikipedia: Callback (computer science)
C# has delegates for that purpose. They are heavily used with events, as an event can automatically invoke a number of attached delegates (event handlers).
A callback is a function that will be called when a process is done executing a specific task.
The usage of a callback is usually in asynchronous logic.
To create a callback in C#, you need to store a function address inside a variable. This is achieved using a delegate or the new lambda semantic Func or Action.
public delegate void WorkCompletedCallBack(string result);
public void DoWork(WorkCompletedCallBack callback)
{
callback("Hello world");
}
public void Test()
{
WorkCompletedCallBack callback = TestCallBack; // Notice that I am referencing a method without its parameter
DoWork(callback);
}
public void TestCallBack(string result)
{
Console.WriteLine(result);
}
In today C#, this could be done using lambda like:
public void DoWork(Action<string> callback)
{
callback("Hello world");
}
public void Test()
{
DoWork((result) => Console.WriteLine(result));
DoWork(Console.WriteLine); // This also works
}
Definition
A callback is executable code that
is passed as an argument to other code.
Implementation
// Parent can Read
public class Parent
{
public string Read(){ /*reads here*/ };
}
// Child need Info
public class Child
{
private string information;
// declare a Delegate
delegate string GetInfo();
// use an instance of the declared Delegate
public GetInfo GetMeInformation;
public void ObtainInfo()
{
// Child will use the Parent capabilities via the Delegate
information = GetMeInformation();
}
}
Usage
Parent Peter = new Parent();
Child Johny = new Child();
// Tell Johny from where to obtain info
Johny.GetMeInformation = Peter.Read;
Johny.ObtainInfo(); // here Johny 'asks' Peter to read
Links
more details for C#.
A callback is a function pointer that you pass in to another function. The function you are calling will 'callback' (execute) the other function when it has completed.
Check out this link.
If you referring to ASP.Net callbacks:
In the default model for ASP.NET Web
pages, the user interacts with a page
and clicks a button or performs some
other action that results in a
postback. The page and its controls
are re-created, the page code runs on
the server, and a new version of the
page is rendered to the browser.
However, in some situations, it is
useful to run server code from the
client without performing a postback.
If the client script in the page is
maintaining some state information
(for example, local variable values),
posting the page and getting a new
copy of it destroys that state.
Additionally, page postbacks introduce
processing overhead that can decrease
performance and force the user to wait
for the page to be processed and
re-created.
To avoid losing client state and not
incur the processing overhead of a
server roundtrip, you can code an
ASP.NET Web page so that it can
perform client callbacks. In a client
callback, a client-script function
sends a request to an ASP.NET Web
page. The Web page runs a modified
version of its normal life cycle. The
page is initiated and its controls and
other members are created, and then a
specially marked method is invoked.
The method performs the processing
that you have coded and then returns a
value to the browser that can be read
by another client script function.
Throughout this process, the page is
live in the browser.
Source: http://msdn.microsoft.com/en-us/library/ms178208.aspx
If you are referring to callbacks in code:
Callbacks are often delegates to methods that are called when the specific operation has completed or performs a sub-action. You'll often find them in asynchronous operations. It is a programming principle that you can find in almost every coding language.
More info here: http://msdn.microsoft.com/en-us/library/ms173172.aspx
Dedication to LightStriker:
Sample Code:
class CallBackExample
{
public delegate void MyNumber();
public static void CallMeBack()
{
Console.WriteLine("He/She is calling you. Pick your phone!:)");
Console.Read();
}
public static void MetYourCrush(MyNumber number)
{
int j;
Console.WriteLine("is she/he interested 0/1?:");
var i = Console.ReadLine();
if (int.TryParse(i, out j))
{
var interested = (j == 0) ? false : true;
if (interested)//event
{
//call his/her number
number();
}
else
{
Console.WriteLine("Nothing happened! :(");
Console.Read();
}
}
}
static void Main(string[] args)
{
MyNumber number = Program.CallMeBack;
Console.WriteLine("You have just met your crush and given your number");
MetYourCrush(number);
Console.Read();
Console.Read();
}
}
Code Explanation:
I created the code to implement the funny explanation provided by LightStriker in the above one of the replies. We are passing delegate (number) to a method (MetYourCrush). If the Interested (event) occurs in the method (MetYourCrush) then it will call the delegate (number) which was holding the reference of CallMeBack method. So, the CallMeBack method will be called. Basically, we are passing delegate to call the callback method.
Please let me know if you have any questions.
Probably not the dictionary definition, but a callback usually refers to a function, which is external to a particular object, being stored and then called upon a specific event.
An example might be when a UI button is created, it stores a reference to a function which performs an action. The action is handled by a different part of the code but when the button is pressed, the callback is called and this invokes the action to perform.
C#, rather than use the term 'callback' uses 'events' and 'delegates' and you can find out more about delegates here.
callback work steps:
1) we have to implement ICallbackEventHandler Interface
2) Register the client script :
String cbReference = Page.ClientScript.GetCallbackEventReference(this, "arg", "ReceiveServerData", "context");
String callbackScript = "function UseCallBack(arg, context)" + "{ " + cbReference + ";}";
Page.ClientScript.RegisterClientScriptBlock(this.GetType(), "UseCallBack", callbackScript, true);
1) from UI call Onclient click call javascript function for EX:- builpopup(p1,p2,p3...)
var finalfield= p1,p2,p3;
UseCallBack(finalfield, ""); data from the client passed to server side by using UseCallBack
2) public void RaiseCallbackEvent(string eventArgument) In eventArgument we get the passed data
//do some server side operation and passed to "callbackResult"
3) GetCallbackResult() // using this method data will be passed to client(ReceiveServerData() function) side
callbackResult
4) Get the data at client side:
ReceiveServerData(text) , in text server response , we wil get.
A callback is a function passed as an argument to another function. This technique allows a function to invoke the parameter function argument and even to pass a value back to the caller. A callback function can be designed to run before/after the function has finished and can pass a value.
It is a kind of construct where you call a long running function and ask him to call you back once it has finished with can return a parameter result to the caller.
It's like someone calls you in the middle of your work asking for status and you say "you know what give me 5 min and i will call you back" and at the end you call him to update. If you are a function the caller just added and passed another function that you invoked at the end. This can simpley be written in C# as:
public void VinodSrivastav(Action statusUpdate){
//i am still here working..working
//i have finished, calling you
statusUpdate();
}
//invokes
stackoverflow.VinodSrivastav((cam) => {
Console.Write("Is it finished");
});
The one simple example is the iterator function where the return will be multiple times, one can argue that we have yield for it:
public void IntreationLoop(int min, int max,Action<int> Callback)
{
for(int i = min;i<= max;i++)
Callback(i);
}
//call
IntreationLoop(5,50,(x) => { Console.Write(x); }); //will print 5-50 numbers
In the code above the function return type is void but it has an Action<int> callback which is called and sends each item from the loop to the caller.
The same thing can be done with if..else or try..catch block as:
public void TryCatch(Action tryFor,Action catchIt)
{
try{
tryFor();
}
catch(Exception ex)
{
Console.WriteLine($"[{ex.HResult}] {ex.Message}");
catchIt();
}
}
And call it as:
TryCatch(()=>{
int r = 44;
Console.WriteLine("Throwing Exception");
throw new Exception("something is wrong here");
}, ()=>{
Console.WriteLine("It was a mistake, will not try again");
});
In 2022 we have Func & Action doing the same, please see the demo code below which shows how this can be be used:
void Main()
{
var demo = new CallbackDemo();
demo.DoWork(()=> { Console.WriteLine("I have finished the work"); });
demo.DoWork((r)=> { Console.WriteLine($"I have finished the work here is the result {r}"); });
demo.DoWork(()=> { Console.WriteLine($"This is passed with func"); return 5;});
demo.DoWork((f)=> { Console.WriteLine($"This is passed with func and result is {f}"); return 10;});
}
// Define other methods and classes here
public class CallbackDemo
{
public void DoWork(Action actionNoParameter)
{
int a = 5;
int b = 10;
//i will do th maths and call you back
int result = a + b;
//callback
actionNoParameter(); //execute
Console.WriteLine($"[The Actual Result is {result}]");
}
public void DoWork(Action<int> actionWithParameter)
{
int a = 5;
int b = 10;
//i will do th maths and call you back
int result = a + b;
//callback
actionWithParameter(result); //execute
Console.WriteLine($"[The Actual Result is {result}]");
}
public void DoWork(Func<int> funcWithReturn)
{
int a = 5;
int b = 10;
//i will do th maths and call you back
int result = a + b;
//callback
int c = funcWithReturn(); //execute
result += c;
Console.WriteLine($"[The Actual Result is {result}]");
}
public void DoWork(Func<int,int> funcWithParameter)
{
int a = 5;
int b = 10;
//i will do th maths and call you back
int result = a + b;
//callback
result += funcWithParameter(result); //execute
Console.WriteLine($"[The Actual Result is {result}]");
}
}