How to pass code blocks (not full methods) as arguments in C#? - c#

I'm building a messaging app in csharp (.net 4.0), my class has basic methods for sending/receiving messages:
void sendMessage( string msgBody, string properties);
object getNextMessage();
object getMessageById( string msgId);
Each of these methods depends on an underlying connection; if the connection is stale, I use try/catch and some retry logic to make additional attempts, something like this:
public object getNextMessage(){
object nextMessage = null;
int retryAttempts = 0;
int MAX_ATTEMPTS = 3;
while( retryAttempts < MAX_ATTEMPTS){
retryAttempts++;
try{
nextMessage = connection.getMessage("queueName");
}catch(Exception e){
}
}
return nextMessage;
}
Since the retry logic is generic, I want to avoid repeating the same code in each method. I want to create a common retry function and do something like this:
public object makeAttempt( CodeBlock codeBlock){
while( retryAttempts < MAX_ATTEMPTS){
retryAttempts++;
try{
return codeBlock.invoke()
}catch(Exception e){
}
}
return null;
}
..I want to use makeAttempt like this, or something similar:
public object getNextMessage(){
makeAttempt() => {
return connection.getMessage("queueName");
}
}
I reviewed this, but it relates to passing entire functions as arguments, which I'm not doing. I also reviewed .net Lambda Expressions, but I'm not seeing a connection.
I haven't done much C# so forgive the n00b question :-)

You're nearly there at the end - you just need to enclose the lambda expression in () as it's a method argument. You also need to use the return value from makeAttempt to provide a return value for your getNextMessage method. So:
public object getNextMessage(){
return makeAttempt(() => {
return connection.getMessage("queueName");
});
}
Or more simply, use an expression lambda:
public object getNextMessage(){
return makeAttempt(() => connection.getMessage("queueName"));
}
This is all assuming that CodeBlock is a delegate type, of course, e.g.
public delegate object CodeBlock();
You also need to change makeAttempt to call Invoke rather than invoke - C# is case-sensitive. I'd strongly urge you to follow .NET naming conventions, too, where methods are PascalCased instead of camelCased.
EDIT: As noted in comments, you could make this generic:
public T CallWithRetries<T>(Func<T> function)
{
for (int attempt = 1; attempt <= MaxAttempts; attempt++)
{
try
{
return function();
}
catch(Exception e)
{
// TODO: Logging
}
}
// TODO: Consider throwing AggregateException here
return default(T);
}

Related

How to return all values after an if then statement in C#

So I am writing a c# program where the client recieves a character from ther server, and runs a background worker depending on which character it reiceves. The problem though is the button states not all code paths return a value:
private object SL_Click(object sender, EventArgs e)
{
try
{
TcpClient tcpclnt = new TcpClient();
Console.WriteLine("Connecting.....");
tcpclnt.Connect(RecieveIP.Text, 8001); // use the ipaddress as in the server program
MessageBox.Show("Connected");
Console.Write("Enter the string to be transmitted : ");
String str = Console.ReadLine();
Stream stm = tcpclnt.GetStream();
ASCIIEncoding asen = new ASCIIEncoding();
byte[] ba = asen.GetBytes(str);
MessageBox.Show("Transmitting.....");
stm.Write(ba, 0, ba.Length);
byte[] bb = new byte[100];
int k = stm.Read(bb, 0, 100);
for (int i = 0; i < k; i++)
Console.Write(Convert.ToChar(bb[i]));
string toattk = k.ToString();
if (toattk == "g")
{
googlesearch.RunWorkerAsync();
}
else if (toattk == "y")
{
ysearch.RunWorkerAsync();
}
else if (toattk == "a")
{
aolsearch.RunWorkerAsync();
}
else if (toattk == "yo")
{
youtubesearch.RunWorkerAsync();
}
else if (toattk == "s")
{
ssearch.RunWorkerAsync();
}
tcpclnt.Close();
}
catch (Exception)
{
MessageBox.Show("Could not find server computer.");
}
}
It says SLCLick - not all code paths return a value. This seems odd as there is an action for every if then statement? Thanks very much.
the method need to return object
private object SL_Click(object sender, EventArgs e){
.....
return whatObject
}
or change return type to void
private void SL_Click(object sender, EventArgs e){
.....
}
This seems odd as there is an action for every if then statement?
This isn't what the compiler is complaining about. Indeed it's possible to write if statements that do nothing:
if(someVariable == someValue){
} else {
}
That's perfectly legal C#; "not all code paths return a value" is not about your method here calling off into some other method at various opportunities
The message arises because you made a promise here:
private object SL_Click
^^^^^^
"I promise to return something"
and you haven't fulfilled it; a method that declares some type of object will be returned must, somewhere within its body code, have return ...something here....
The "something here" must be of a Type that is (convertible to) the Type you promised in the method header
You cannot:
public string MyMethod(){. //I promise to return a string
return 1; //not a string, not implicitly convertible to a string
}
Further, there must be no detectable route through the code, through all the ifs and elses etc, that means C# can get to the end of the method without hitting a return ...something here...
public string MyMethod(){ //I promise to return a string
if(DateTime.Today.DayOfWeek == DayOfWeek.Monday){
return "Hello";
}
}
This also gives "not all paths return a value" - you have to completely and explicitly tell C# what to do in every case; you can't just leave it to decide itself what to return if it's Tuesday
If you don't plan to return anything, declare the method void:
public void MyMethod(){
if(DateTime.Today.DayOfWeek == DayOfWeek.Monday){
return; //I don't work Mondays
}
}
You can still quit early in a void method, by doing a return without a value after it. Also you can let C# reach the end without encountering any return - C# knows what to do if it reaches the end of a void method without having encountered a return, but for anything non-void you have to be explicit about what value to return on every possible path through the code
In your case I'd say it should be a void method. Try also to avoid returning object - use a more specific type if you can.
We'll get to Task-returning methods some other time :)
Small additional, because it's bound to come up for you soon- how do you return more than one value? In C# you can only ever return one thing. If you want to return multiple values, you're free to make something that holds multiple values, make one of those things and put your multiple values inside it.
That one thing could be an array, a dedicated class, some built in convenient like a a tuple or anonymous type.. but all in remember you can only return one thing; if you have lots of values to return, put them inside one thing and return that.
It's like working in a bar and needing to carry 10 different drinks on one hand; you put the drinks on a tray and carry the tray.
I think this is an event handler, and if you look closely your method demands an object to be returned private object SL_Click(object sender, EventArgs e).
If you can, then change the return type of the method from object to void
private object SL_Click(object sender, EventArgs e)
In case you can't change the method signature, then you can just simple return any object (provided you don't need to return anything) at the end of the try and catch or add a finally block and return a dummy object.
finally
{
return "Event Handled";
}

C# - Try something twice if if-statement is true

I have a code parsing a website and adding some values to a list. Sometimes I need to parse the website two times and add the second parsevalues to the same list.
This is some of the code:
public async Task<IEnumerable<Info>>....
{
var values = new List<Info>();
var request = something;
var request_rewritten = rewritten request to run the second time;
......
if request contains something do all the under two times. Both for the request and the rewritten request and add it to result.
......
var response = await RequestBytes(request);
var results = Encoding.GetEncoding("iso-8859-1").GetString(response.Content);
_fDom = results;
try
{
do something and a lot of code
......
values.Add(result);
return result
}
}
If request contains something I need try try a second time. Both for the original request and the rewritten request and add both to the result. Can this be done?
You can follow this pattern. Add an additional parameter to your method indicating retries remaining.
void DoSomething(arg1, arg2, int retriesRemaining = 0)
{
try
{
DoWork();
}
catch
{
if (retriesRemaining) DoSomething(arg1, arg2, --retriesRemaining);
}
}
I suppose if you want to avoid writing a method (which is the best answer to your question) you can use a flag:
bool bRunAgain = true;
while (bRunAgain)
{
// Your logic, check result and see if you need to run it again
if (your condition to run again == false)
{
bRunAgain = false;
}
}
Here is a common solution. Pass an action to this method and specify retries count
public bool ExecuteWithRetry(Action doWork, int maxTries=1) {
for(var tryCount=1; tryCount<=maxTries; tryCount++){
try{
doWork();
} catch(Exception ex){
if(tryCount==MaxTriex){
Console.WriteLine("Oops, no luck with DoWork()");
return false;
}
}
return true;
}
}
so in your method
void Something(){
....
if(ExecuteWithRetry(()=>NotTrustyMethod(), 2)) {
//success
} else {
//fail
}
}
void NotTrustyMethod(){ ...}
This solution you can use for any case where you need retry option for methods with any type of arguments (or without them)

can a value be stored in variable returned by a function called as a parameter

Hi I was integrating facebook SDK in unity and basically I worked in java earlier and I am new to c# script and a question came to my mind.
I have searched a lot found nothing, may be my searching query is good enough or not but my question is ...
as a function FB.init called here
void Awake ()
{
FB.Init(InitCallback, OnHideUnity);
}
here when init function will be called it will call InitCallBack and OnHideUnity functions and both are returning void these are used form facebook-unity-sdk docs
private void InitCallback ()
{
if (FB.IsInitialized) {
// Signal an app activation App Event
FB.ActivateApp();
// Continue with Facebook SDK
// ...
} else {
Debug.Log("Failed to Initialize the Facebook SDK");
}
}
private void OnHideUnity (bool isGameShown)
{
if (!isGameShown) {
// Pause the game - we will need to hide
Time.timeScale = 0;
} else {
// Resume the game - we're getting focus again
Time.timeScale = 1;
}
}
My question is if I call a function like this and that function return something e.g String and I want wanted to store it something like this
String result="";
SomeFunctions(FunctionOne,result=FunctionTwo);
String FunctionTwo()
{
return "a String";
}
Is this possible?
Is there any way to get value returned by such function call?
Or is this possible that a function that returns value can be called in this way?
It seems like you are confusing a delegate for a function expression. The delegate will have no return value until it is invoked as a function.
void SomeFunction(Func<string> func) {
var result = func(); // only here will the function return value be accessible
Console.WriteLine(result);
}
SomeFunction(() => "test");
Although you do not have access to the return value of the function, the delegate could assign a variable you choose inside it's method body, instead of using it's return value:
string result;
SomeFunction(() => {
result = "test";
return result;
});
// result would now contain "test"
I am not sure what you want to achieve here, but you could use out to change the reference of the parameter.
string result="";
MyMethod(out result);
Debug.Log(string.Format("Result: {0}", result));
void MyMethod(out string pValue)
{
pValue = "my changed value";
}
The out keyword causes arguments to be passed by reference. This is like the ref keyword, except that ref requires that the variable be initialized before it is passed. To use an out parameter, both the method definition and the calling method must explicitly use the out keyword.
https://msdn.microsoft.com/en-us/library/t3c3bfhx.aspx
But in a case like this, you could just return the correct value. In the example below its not even worth passing the parameter since we are not using it.
string result = MyMethod(result);
string MyMethod(string pValue)
{
pValue = "My changed value";
return pValue;
}

Access to modified closure: ReSharper

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.

Using Action<T> as an argument in C# (mimicking a function pointer)

I need to write a delegate function that can 'wrap' some while/try/catch code around a basic UDP call to verify the link.
I made it work for Func for a function that has no arguments, but I can't make it work for Action, which has an argument (but no return). I can't seem to pass in the argument in a logical way without the compiler complaining.
Am I going about this all wrong? I'm new to C# and I'm essentially trying to mimick the idea of a function pointer. Should I not be overloading this function? I know you can't overload delegates (I assume that's why Func and Action exist).
This works:
protected TResult udpCommand<TResult>(Func<TResult> command)
{
TResult retValue = default(TResult);
while (!linkDownFail)
{
try
{
retValue = command();
break;
}
catch
{
LinkStateCallBack(ip, getLinkStatus());
if (linkDownFail) throw new LinkDownException();
Thread.Sleep(100);
}
}
return retValue;
}
But this does not:
protected void udpCommand<T>(Action<T> command(T value))
{
while(!linkDownFail)
{
try
{
command(value);
break;
}
catch
{
LinkStateCallBack(ip, getLinkStatus());
if (linkDownFail) throw new LinkDownException();
Thread.Sleep(100);
}
}
return;
}
Calling convention (for one that works):
udpCommand<uint>(someUdpCommand);
If you want this to be generic enough to handle any number of arguments, try using the non-genernic Action delegate:
protected void udpCommand(Action command)
{
while(!linkDownFail)
{
try
{
command();
break;
}
catch
{
LinkStateCallBack(ip, getLinkStatus());
if (linkDownFail) throw new LinkDownException();
Thread.Sleep(100);
}
}
return;
}
In C# 3.0, you can call it like this:
udpCommand(() => noParameterMethod());
udpCommand(() => singleParameterMethod(value));
udpCommand(() => manyParameterMethod(value, value2, value3, value4));
In C# 2.0 it's a little uglier:
udpCommand(delegate { noParameterMethod(); });
udpCommand(delegate { singleParameterMethod(value); });
udpCommand(delegate { manyParameterMethod(value, value2, value3, value4); });
This gives you deferred execution without locking you into a particular method signature.
EDIT
I just notice I kinda stole Marc Gravell's comment... apologies Marc. To answer how you might reduce your duplication, you can have the Action method call the Func<T> method, like this:
protected void udpCommand(Action command)
{
udpCommand(() => { command(); return 0; });
}
I believe (and I may be wrong) that returning 0 is no more costly than (implicitly) returning void, but I may be way off here. Even it it does have a cost, it would only put a tiny itty bitty snoodge extra on the stack. In most cases, the additional cost won't ever cause you any grief.
Do you mean:
protected void udpCommand<T>(Action<T> command, T value) {...}
With calling:
udpCommand(someUdpCommand, arg);
Note that this may work better on C# 3.0, which has stronger generic type inference than C# 2.0.
I think you just need to take out the (T value) after 'command'.
Are you trying to do this ...
protected void udpCommand<T>(Action<T> command, T value)
{
while(!linkDownFail)
{
try
{
command(value);
// etc.
}
}
}
Then it would work like this ...
public void ActionWithInt( int param )
{
// some command
}
Action<int> fp = ActionWithInt;
udpCommand<int>( fp, 10 ); // or whatever.

Categories