Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
I have two function with different functionality and i want to call them based on some value. without if else or switch case block. like i have
Dictionary<string, string> intentMap = new Dictionary<string, string>();
intentMap.Add("rootIntent", "TicketbookingInformation");
intentMap.Add("rootIntent", "OrderInformation");
and i have two function
public bool BookTicket()
{
// to do
}
public bool BookOrder()
{
// to do
}
I want to switch these function if intentMap has TicketbookingInformation then call BookTicket method or if intentMap has OrderInformation then call BookOrder method.
I want to do in generic way using deleagtes so in future if I have some more use case (new method), so i can utilize the same functionlaity without modifying much.
Use another dictionary, this time of type <string, Func<bool>:
var delegateMap = new Dictionary<string, Func<bool>>()
{
{ "TicketBookingInformation", BookTicket },
{ "OrderInformation", BookOrder }
};
foreach (var intent in intentMap)
{
bool result = delegateMap[intent.Value]();
}
I won't answer to your question directly. #Abion47 has answered perfectly fine, i would answer the same.
But i think having having two dictionaries one having the token, and another having the delegate is more obscure then having single method for dispatching the result.
Here is my point with a bit code.
This the dictionary version.
var intentMap = new Dicionary<string, string>();
var delegateMap = new Dictionary<string, Func<bool>>();
delegate.Map.Add("TicketbookingInformation", BookTicket);
delegateMap.Add("OrderInformation", BookOrder);
Then the usage will be something like this
var token = ...;
if(intentMap.ContainsKey(token))
{
var delegateToken = intenMap[token];
if(delegateMap.ContainsKey(delegateToken))
{
var delegatedMethod = delegateMap(delegateToken);
return delegatedMethod();
}
}
So adding new token and delegate will means extending the dictionaries and i can't see how this is different then extending a switch statement.
Second version which i think will be generic enough and will need not too much modification where used will be something like this.
First i will suggest having the "TicketbookingInformation" and "OrderInformation" as enumeration type, this way having a switch statement will benefit from the compiler helping when you have some missing case to handle. This of course is applicable if you know upfront all the possible values ;]
bool PredicateDispatch(DelegateToken token)
{
switch(token)
{
DelegateToken.TicketbookingInformation: return BookTicket();
DelegateToken.OrderInformation: return BookOrder()
}
}
this way you will need to extend this single method to handle new tokens. It is more readable approach and you don't lose anything compared with the dictionary version. So i will do it this way. If don't have of course more complicated code and your example is more more simplified ;]
Related
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 4 years ago.
Improve this question
I am trying to assert whether two or more strings are evident. My code currently only looks for "Good". Is there a way to look for "Good" or "Bad"?
public class Test
{
public static bool FindText()
{
var conf = Driver.Instance.FindElement(By.Id("foo"));
if (conf.Text.Contains("Good"))
{
return true;
}
throw new Exception("Text not found");
}
}
I would use System.Linq and check against all elements of an array, if there could possibly be more than two valid strings.
public class Test
{
public static bool FindText()
{
var stringsToFind = new [] { "Good", "Bad" };
var conf = Driver.Instance.FindElement(By.Id("foo"));
if (stringsToFind.Any(s => conf.Text.Contains(s))
{
return true;
}
throw new Exception("Text not found");
}
}
for only two elements to check I would propably just extend the if condition with a second condition and an or.
When trying to find a string, always make the string variable to upper or lower case. Since it's case sensitive, when the text is "GoOd", you won't find a match looking for "Good"
if(conf.Text.ToUpper().Contains("GOOD")){
//do something
}
else if(conf.Text.ToUpper().Contains("BAD")){
//do something else
}
You could also put then in only one "if" statement, if you're only interested in finding out if there's any of those by using
if(conf.Text.ToUpper().Contains("GOOD") || conf.Text.ToUpper().Contains("BAD")){
//do something for both cases
}
|| is the operator for the OR operation
if (conf.Text.Contains("Good") || conf.Text.Contains("Bad"))
PD : Stop whatever you are doing and take a look to the language docs, you need to understand what are you doing.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 5 years ago.
Improve this question
First of all sorry if this is a duplicate. I dont exactly know how to search for this.
I have a question about how to be able to use a saved string to change what type of method I call
MenuBar.Dock = Dockstyle.DockStyleString //DockStyleString is a string defined somewhere with either Top or Bottom
So, according to your example you seem to be using an enumerator. Enum has utilities that would 'convert' a string into the right enum value. Also you can have an utility class that does that for you.
DockstyleUtils.FromString("DockStyleString");
This would return an enum Dockstyle.DockstyleString.
So, you can use it MenuBar.Dock = DockstyleUtils.FromString("DockStyleString");
I created this method you can use...
public DockStyle ConvertDockingStyleFromString(string dockingStyle)
{
return (DockStyle)Enum.Parse(typeof(DockStyle), dockingStyle);
}
There you go.
Some of this depends on what you want to do with the string once you have it. You can use the code in #PepitoFernandez's answer to convert it to an enum. If you'd like to then use it to determine what method to call against an object, you have a few options.
The first is that if it's a known set of strings, you could use a switch statement:
switch (stringVariable) {
case "stringA": methodA(); break;
case "stringB": methodB(); break;
...
// If you get a "bad" string, you WANT to throw an exception to make
// debugging easier
default: throw new ArgumentException("Method name not recognized");
}
Obviously, you can also replace this with enum values if you do the conversion first. (That's actually not a bad idea because if you get a "bad" string you
The other option (if you want to do it dynamically at runtime) is to do the call using reflection, like this:
public class SomeClass
{
public void MethodA()
{
Console.WriteLine("MethodA");
}
}
static void Main(string[] args)
{
Type type = typeof(SomeClass);
// Obviously, you'll want to replace the hardcode with your string
MethodInfo method = type.GetMethod("MethodA");
SomeClass cls = new SomeClass();
// The second argument is the parameters; I pass null here because
// there aren't any in this case
method.Invoke(cls, null);
}
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
In case of situations to use multiple params type parameters in methods what is the alternate because i get error while trying to use multiple params type parameters
Use plain arrays instead:
public void Method( /*remove params*/ string[] first
, /*optionally remove params*/ int[] second
)
{ }
Call it:
Method(new string[] { ... }, new int[] { ... } );
Optionally, you could leave the last params as is, since it can only be one per method and must be the last one, according to MSDN:
No additional parameters are permitted after the params keyword in a method declaration, and only one params keyword is permitted in a method declaration.
For simplistic use, I'd go with the solution Patrick Hofman supplied. Although, whenever you want to do something more type specific and including a wider range of types, I'd say you should be using params.
public class Bar { }
public void Foo(params object[] objs)
{
foreach(object obj in objs)
{
Type typeofObject = obj.GetType();
if (typeofObject == typeof(string))
{
// Its a string
}
else if (typeofObject == typeof(int))
{
// Its an integer
}
else if (typeofObject == typeof(Bar))
{
// Its an Bar object
}
}
}
Calling the method:
Bar bar = new Bar();
this.Foo("hi", 1, bar);
But again, this isn't the right solution if you only have 2/3 types.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 9 years ago.
Improve this question
By seeing this solution specified in Divide Foreach into threads sample
I tried to implement it with this code:
foreach (Object vo in arrreclist)
{
msg = String.Empty;
objprocess.GetType().GetMethod("ProcessRecord").Invoke(objprocess, new Object[] { vo });
status = (StatusInfo)objprocess.GetType().GetProperty("status").GetValue(objprocess, null);
if (status.errcode != 0)
{
lngfailedcnt++;
WriteErrorLog();
}
else
{
lngsuccesscnt++;
lngInstanceSuccCount++;
}
lngcnt++;
if ((lngcnt % 10) == 0)
{
if (instanceId == 0)
{
schldr.ModifyJobhistoryForUploadFileRecCnt(Runid, (int)lngTotreccnt, lngfailedcnt, (int)(lngfailedcnt + lngsuccesscnt));
}
else
{
schldr.ModifyJobhistoryForUploadFileRecCnt(Runid, 0, lngfailedcnt, (int)(lngfailedcnt + lngsuccesscnt));
}
status = schldr.status;
if (status.errcode != 0)
{
if (!String.IsNullOrEmpty(Errorlogfile))
WriteErrorLog();
holdInstance = true;
break;
}
//Get Job Status
//If job was terminated then Update Batch and Job history with status as STOPPED
intstatus = schedulersvc.GetJobStatus(Runid);
status = schedulersvc.status;
if (status.errcode != 0)
{
WriteErrorLog();
holdInstance = true;
break;
}
if (intstatus == 1) //STOPPED
{
holdInstance = true;
break;
}
lngcnt = 0;
}
}
And error message is coming for break statement:
cannot leave the body of anonymous method or lambda expression
My major task is to parallelize the following line:
objprocess.GetType().GetMethod("ProcessRecord").Invoke(objprocess, new Object[] { vo })
But other are dependents so how to implement?
First, parallelization often doesn't make sense in ASP.NET. If you have many users accessing your site, you usually care more about scalability (how many users can you serve at the same time), than raw performance for single user.
If that's not your case, parallelization might make sense for you.
Second, you're getting that error, because Parallel.ForEach() is not a loop (as far as the language is concerned). And breaking out of a lambda doesn't make any sense.
To break out of Parallel.ForEach(), you can use ParallelLoopState.Break() or ParallelLoopState.Stop() (read the documentation to find out which one of those do you actually want). To do this, you will need to use an overload of Parallel.ForEach() that gives you that ParallelLoopState.
Third, there is a good reason why Parallel.ForEach() doesn't support ArrayList: it's because you should never use it. If you really want a list of objects, use List<object> to make it clear that you really don't know the type. If you can't (or don't want to) change the ArrayList, you can use .Cast<object>() to make Parallel.ForEach() (and other methods that work with IEnumerable<T>) accept it.
Fourth, I think that parallelizing just the ProcessRecord doesn't make sense. It looks like status returns the status for the last ProcessRecord. And if you execute ProcessRecord in parallel, then it's not clear anymore which one is the last.
Also, you shouldn't think that some method is not thread-safe. You should know that. If you parallelize something that you don't know is thread-safe, you're likely to get hard to debug bugs later on.
Fifth, if you want to parallelize just the first part of a loop, I think the best option is PLINQ. Something like:
var intermediateResults = source.AsParallel().Select(x => Process(x));
foreach (var intermediateResult in intermediateResults)
{
// the rest of the loop
}
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 8 years ago.
Improve this question
I'm curious if there is a preferred approach to my problem. Basically, I have some data (it's xml) and I need to amend the data to add some attributes lets say. For this I have written a method to do it for me. Then I need to use the modded data later. Should the method return void or the required data type?
Option 1:
var someData = GetTheData();
someData = ModifyTheData(someData);
Option 2:
var someData = GetTheData();
ModifyTheData(someData, out someData);
Are there any differences between using these 2 versions? Would I be right in thinking that option 1 would create 2 instances in memory (1 for the someData variable and 1 for the return value of the method) but option 2 would only have 1 instance?
Is there a preferred approach? It doesn't matter too much, I'm just curious
Many Thanks
Would I be right in thinking that option 1 would create 2 instances in memory (1 for the someData variable and 1 for the return value of the method) but option 2 would only have 1 instance?
That would depend on the implementation of the ModifyTheData method and whether the type of someData is reference or value type. If you only assign the out variable to the first argument both will be equivalent if someData is a reference type:
public void ModifyTheData(SomeData someData, out SomeData data)
{
someData.Foo = "bar";
data = someData;
}
is the same as:
public SomeData ModifyTheData(SomeData someData)
{
someData.Foo = "bar";
return someData;
}
is the same as:
public void ModifyTheData(SomeData someData)
{
someData.Foo = "bar";
}
I'd like to avoid out parameters as much as possible.
In your case, I think it is better to return the modified data. It is imho more readable and more comprehensive.