How to return value with this issue?
Help me please.
protected string SendState(Object ID_DIP,Object ID_SEQ,Object MODUL)
{
try
{
ViewState["ssDIP"] = ID_DIP.ToString();
ViewState["ssSEQ"] = ID_SEQ.ToString();
ViewState["ssMOD"] = MODUL.ToString();
return ID_DIP.AsString();
return ID_SEQ.AsString();
return MODUL.ToString();
}
catch (Exception)
{
return "";
}
}
You have multiple return statements, your code will not execute statements after first return statement. You can't return multiple values from your method, if you want to return multiple values you can either return List<string> for your case or create a temporary class and return its object.
In your code you are using AsString, I think you probably meant ToString
Define a class like:
public class MyReturnObject
{
public string ID_DIP { get; set; }
public string ID_SEQ { get; set; }
public string MODUL { get; set; }
}
Modify your method like:
protected MyReturnObject SendState(Object ID_DIP, Object ID_SEQ, Object MODUL)
{
try
{
ViewState["ssDIP"] = ID_DIP.ToString();
ViewState["ssSEQ"] = ID_SEQ.ToString();
ViewState["ssMOD"] = MODUL.ToString();
MyReturnObject obj = new MyReturnObject();
obj.ID_DIP = ID_DIP.ToString();
obj.ID_SEQ = ID_SEQ.ToString();
obj.MODUL = MODUL.ToString();
return obj;
}
catch (Exception)
{
return null;
}
}
first thing is u have multiple return values, so ur code wouldn't work, so u can use List<String> & to return in catch case, u could use a var at the top of method definition, like this--->
public List<string> SendState(Object ID_DIP,Object ID_SEQ,Object MODUL)
{
var returnValue = new List<string>();
try
{
ViewState["ssDIP"] = ID_DIP.ToString();
ViewState["ssSEQ"] = ID_SEQ.ToString();
ViewState["ssMOD"] = MODUL.ToString();
returnValue.add(ID_DIP.AsString());
returnValue.add(ID_DIP.AsString());
returnValue.add(MODUL.ToString());
}
catch (Exception)
{
returnValue = null;
}
return returnValue;
}
now u can use the above method like this--->
var result = SendState( params ) //<--- params r ur parameters
if(result != null)
// proceed
else
// no value found
If you want return multiple results which has the same type. I suggest you should apply coroutine pattern. Specifics at here as code below:
protected IEnumerable<string> SendState(Object ID_DIP,Object ID_SEQ,Object MODUL)
{
ViewState["ssDIP"] = ID_DIP.AsString();
ViewState["ssSEQ"] = ID_SEQ.AsString();
ViewState["ssMOD"] = MODUL.ToString();
yield return ID_DIP.AsString();
yield return ID_SEQ.AsString();
yield return MODUL.ToString();
}
You take reference the link to get more understand about coroutine pattern in C#.
In C#, methods generally return only one value. This value can be an object with multiple fields.
If you need to return multiple values from a method, you can use out parameters or return a type instance containing all the values.
As Habib suggested, returning List<string> is a good approach in your case.
You can only return a single value from a method, so of your three return statements only the first one will execute.
If you want to return multiple strings, return an array of strings:
protected string[] SendState(Object ID_DIP,Object ID_SEQ,Object MODUL) {
try {
ViewState["ssDIP"] = ID_DIP.ToString();
ViewState["ssSEQ"] = ID_SEQ.ToString();
ViewState["ssMOD"] = MODUL.ToString();
return new string[] {
ID_DIP.ToString(),
ID_SEQ.ToString(),
MODUL.ToString()
};
} catch (Exception) {
return null; // or perhaps an empty array...?
}
}
Any code that is written after the first return statement (within the same block) will not execute. In case you want to return multiple values from a method, consider using objects.
Related
I want to eliminate some duplicated code. Can anyone make this code shorter and better?
switch (now.site)
{
case item.SITE.AMAZON:
try
{
price = driver.FindElement(By.XPath("//*[#id=\"priceblock_ourprice\"]")).Text;
fetched = true;
}
catch
{
try
{
price = driver.FindElement(By.XPath("//*[#id=\"priceblock_dealprice\"]")).Text;
fetched = true;
}
catch
{
fetched = false;
}
}
break;
case item.SITE.ALI:
try
{
price = driver.FindElement(By.XPath("//*[#id=\"j-sku-discount-price\"]")).Text;
fetched = true;
}
catch
{
try
{
price = driver.FindElement(By.XPath("//*[#id=\"j-sku-price\"]")).Text;
fetched = true;
}
catch
{
fetched = false;
}
}
break;
}
}
You could create a dictionary of available path strings. I don't know what the type of site is. I assume string
private static Dictionary<string, string[]> pricePaths = new Dictionary<string, string[]> {
[item.SITE.AMAZON] = new string[] { "//*[#id=\"priceblock_ourprice\"]",
"//*[#id=\"priceblock_dealprice\"]" },
[item.SITE.ALI] = new string[] { "//*[#id=\"j-sku-discount-price\"]",
"//*[#id=\"j-sku-price\"]" },
};
With this, you can write a more generic logic.
bool fetched = false;
if (pricePaths.TryGetValue(now.site, out string[] paths)) {
foreach (string path in paths) {
try {
price = driver.FindElement(By.XPath(path)).Text;
fetched = true;
break;
} catch {
}
}
}
It allows you to easily add new sites. The sites can have an arbitrary number of alternate paths.
It appears that you're really trying to get a decimal value. Let's use this assumption and make a method that returns a decimal? to indicate success (i.e. a value) or failure (i.e. null).
public static class Ex
{
public static decimal? FindDecimalMaybe(this IWebDriver driver, string path)
{
try
{
if (decimal.TryParse(driver.FindElement(By.XPath(path)).Text, out decimal result))
{
return result;
}
}
catch { } // I hate this, but there doesn't seem to be a choice
return null;
}
}
The purpose of this method is to hide the unpleasant fact that the Selenium library appears to code by exception.
I've also created it as an extension method so that the call to driver.FindElement is replaced by something that looks familiar - driver.FindDecimalMaybe.
Now I take the same approach as Oliver with a dictionary:
private static Dictionary<string, string[]> __pricePaths = new Dictionary<string, string[]>
{
{ item.SITE.AMAZON, new [] { "//*[#id=\"priceblock_ourprice\"]", "//*[#id=\"priceblock_dealprice\"]" } },
{ item.SITE.ALI, new [] { "//*[#id=\"j-sku-discount-price\"]", "//*[#id=\"j-sku-price\"]" } },
};
Now it's trivial to get the values out:
decimal? price =
__pricePaths[now.site]
.Select(path => driver.FindDecimalMaybe(path))
.Where(x => x.HasValue)
.FirstOrDefault();
If the price variable has a value then success, but if it is null then the call did not succeed.
Here are some recommendations as to how you can beautify your code -
Declare constants for all XPath queries.
Declare a variable outside the switch statement to capture the price value based on your case statement.
Create a function with one try catch statements which accepts 2 xPath strings and an out parameter for Price and returns a boolean value to indicate if the query was successful.
Remove the try catch from under each case and call that function passing the correct xPath strings from the set of constants.
const string priceblock_ourprice = "//*[#id=\"priceblock_ourprice\"]";
const string priceblock_dealprice = "//*[#id=\"priceblock_dealprice\"]";
const string j_sku_discount_price = "//*[#id=\"j-sku-discount-price\"]";
const string j_sku_price = "//*[#id=\"j-sku-price\"]";
public void YourPrimaryFunction
{
decimal price;
switch (now.site)
{
case item.SITE.AMAZON:
fetched = FetchPrice(priceblock_ourprice, priceblock_dealprice, out price);
break;
case item.SITE.ALI:
fetched = FetchPrice(j_sku_discount_price, j_sku_price, out price);
break;
}
}
private bool FetchPrice(string xPathPrim, string xPathFallBack, decimal out price)
{
try
{
price = driver.FindElement(By.XPath(xPathPrim)).Text;
return true;
}
catch
{
try
{
price = driver.FindElement(By.XPath(xPathFallBack)).Text;
return true;
}
catch
{
return false;
}
}
}
I often want to parse a string into various bits and have a readable way to return them.
I like this approach, but it involves creating a specific class
long orderID = Utils.UnTradeIdent(tradeIdent).OrderID;
In Utils.cs:
public class TradeIdentData
{
public string AccountIdent;
public long OrderID;
public string SubID;
}
public static TradeIdentData UnTradeIdent(string tradeIdent)
{
TradeIdentData tradeIdentData = new TradeIdentData();
var parts = tradeIdent.Split('!');
tradeIdentData.AccountIdent = parts[0];
if (parts[1].Contains("."))
{
var bits = parts[1].Split('.');
tradeIdentData.OrderID = long.Parse(bits[1]);
tradeIdentData.SubID = bits[1];
}
else
{
tradeIdentData.OrderID = long.Parse(parts[1]);
tradeIdentData.SubID = "";
}
return tradeIdentData;
}
A separate class with well-named properties (which you are already using) is currently the most readable way of doing this.
In C# 7 you will be able to use tuples for return values, like so:
public static (string AccountIdent, string OrderID, string SubID) UnTradeIdent(string tradeIdent)
{
string accountIdent, orderID, subID ;
... Code to initialise accountIdent, orderID and subID appropriately ...
// Now return the data as a tuple:
return (accountIdent, orderID, subID);
}
You can consume this as follows:
long orderID = Utils.UnTradeIdent(tradeIdent).OrderID;
Or if you want all the values:
var result = Utils.UnTradeIdent(tradeIdent);
// Use result.OrderId, result.SubID or result.AccountIdent
This is not going to be available until some time next year, though.
Also, even though this new tuple support makes it more convenient to WRITE the code, it doesn't let you document it using XML comments as well. Spending the time to write a simple and well-documented class will still often be better than using the new C# 7 tuple support.
See here for more details.
You can also use the out keyword to pass arguments by reference, see MSDN article out (C# Reference):
public static void UnTradeIdent(string tradeIdent, out string AccountIdent, out long OrderID, out string SubID)
{
var parts = tradeIdent.Split('!');
AccountIdent = parts[0];
if (parts[1].Contains("."))
{
var bits = parts[1].Split('.');
OrderID = long.Parse(bits[1]);
SubID = bits[1];
}
else
{
OrderID = long.Parse(parts[1]);
SubID = "";
}
}
UPDATED with suggestion from comments:
public static bool UnTradeIdent(string tradeIdent, out string AccountIdent, out long OrderID, out string SubID)
{
bool result = false;
AccountIdent = "";
OrderID = 0;
SubID = "";
try
{
var parts = tradeIdent.Split('!');
AccountIdent = parts[0];
if (parts[1].Contains("."))
{
var bits = parts[1].Split('.');
OrderID = long.Parse(bits[1]);
SubID = bits[1];
}
else
{
OrderID = long.Parse(parts[1]);
SubID = "";
}
}
catch(ArgumentNullException ane)
{
// Handle parsing exception
}
catch (FormatException fe)
{
// Handle parsing exception
}
catch (OverflowException oe)
{
// Handle parsing exception
}
return result;
}
Its pretty simple to do just by changing the return type to dynamic and using an anonymous class
public static dynamic UnTradeIdent(string tradeIdent)
{
var value1 = //parselogic
var value2 = //parselogic
return new { Identity = value1, Item2 = value2};
}
I would consider making additional static methods. Your current implementation is cleaner when you require all of the returned properties, but something like below might be appropriate when you only need one of them.
public static string TradeIdentToAccountIdent(string tradeIdent)
{
var parts = tradeIdent.Split('!');
return parts[0];
}
public static long TradeIdentToOrderID(string tradeIdent)
{
var parts = tradeIdent.Split('!');
if (parts[1].Contains("."))
{
var bits = parts[1].Split('.');
return long.Parse(bits[1]); // Taken from your example, should probably be bits[0]?
}
else
return long.Parse(parts[1]);
}
// My own take on it this time, you could obviously use your logic as well.
public static string TradeIdentToSubID(string tradeIdent)
{
var order = tradeIdent.Split('!')[1];
if (order.Contains("."))
return order.Split('.')[1];
else
return String.Empty;
}
Is there a way to make a function return the type of object I pass in? I would like to call the one method below to return the type I pass in. Is that possible? Should I even be trying to do this? Is there a better way...short of having two different methods?
Currently, I tried the first two calls and I get back (with the first call) what looks like a dictionary with a system.object[] in the value part of the dictionary. Screen shot below might show it better than my explanation. I ask this as I might have more types that I need to deserialize and don't want to have a different method for each.
var firstTry = this.Deserialize(path, typeof(ObservableCollection<ListItemPair>();
var secondTry = this.Deserialize(path, typeof(ListItemPair));
var thirdTry = this.Deserialize(path, typeof(SomeOtherObject));
public static object Deserialize(string jsonFile, object type)
{
var myObject = new object();
try
{
using (StreamReader r = new StreamReader(jsonFile))
{
var serializer = new JavaScriptSerializer();
string json = r.ReadToEnd();
myObject = serializer.Deserialize<object>(json);
}
}
catch (Exception ex)
{
}
return myObject ;
}
public class ListItemPair
{
public string Name
{
get;
set;
}
public object Value
{
get;
set;
}
}
object created:
Yes, you can create a generic method. Your Deserialize() method would look something like this:
public static T Deserialize<T>(string jsonFile)
{
T myObject = default(T);
try
{
using (var r = new StreamReader(jsonFile))
{
var serializer = new JavaScriptSerializer();
string json = r.ReadToEnd();
myObject = serializer.Deserialize<T>(json);
}
}
catch (Exception ex)
{
}
return myObject;
}
In this example T is a type parameter. When invoking this method, you can pass the type like this:
var firstTry = Deserialize<ObservableCollection<ListItemPair>>(path);
var secondTry = Deserialize<ListItemPair>(path);
var thirdTry = Deserialize<SomeOtherObject>(path);
One side note: I wouldn't recommend silently swallowing an exception. In this case, it is expected that the deserialization can fail. Therefore, I would change it to a TryDeserialize() method:
public static bool TryDeserialize<T>(string jsonFile, out T myObject)
{
try
{
using (var r = new StreamReader(jsonFile))
{
var serializer = new JavaScriptSerializer();
string json = r.ReadToEnd();
myObject = serializer.Deserialize<T>(json);
}
}
catch (Exception ex)
{
myObject = default(T);
return false;
}
return true;
}
I have created a list which has soundfragments and contains different fragments with each a unique number.
I need to search for a unique number in the list I made (Soundfragment), if the number is found then I need to return the found number. If it isn't found then I have to return null.
How do I search for a unique number in my list?
class BGExperience
{
private List<Soundfragment> fragmenten; // = new List<Soundfragment>();
private String theme;
/******** constructoren ***************************************************/
public BGExperience(String theme)
{
fragmenten = new List<Soundfragment>();
this.theme = theme;
}
/******** properties ********************************************************/
public String Theme
{
get { return Theme; }
}
/******** methoden ********************************************************/
// returns Soundfragment with nummber nr
// if it is unkown return null
public Soundfragment GetFragment(int nr)
{
}
// returns list with all fragments
public List<Geluidsfragment> GetAlleFragmenten()
{
return fragmenten;
}
You can do the GetFragment method using linq...
var result = fragmenten.Where(s => s.NumberSoundFragment == nr).ToList();
Then you can check if result has no items, return null, and if not, just return the first item!
public Soundfragment GetFragment(int nr)
{
var sFragment = fragmenten.Where(f => f.Number == nr);
if(sFragment.Any()) return sFragment.First();
else return null;
}
I assumed your Soundfragment class has Number property.If it is different change it to your property name.
Or you can do it with one line:
public Soundfragment GetFragment(int nr)
{
return fragmenten.Where(f => f.Number == nr).FirstOrDefault();
}
In QueryableEntities method below,
IEnumerable<Competition>.AsQueryable() will return IQueryable<Competition> which am not able to return because it is expecting IQueryable<T>
I can write only one method to return IQueryable<Competition> and IQueryable<Submission>
If anyone knows how to do it please let me know, thanks
public partial class WinBoutsDataContext<T> : System.Data.Linq.DataContext where T : class
{
public IQueryable<T> QueryableEntities
{
get
{
if (typeof(T).Equals(typeof(Model.Competition)))
{
return this.ConvertToCompetitionList(
this.GetTable<Storage.Competition>()).AsQueryable();
}
else if(typeof(T).Equals(typeof(Model.Submission)))
{
return this.ConvertToSubmissionList(
this.GetTable<Storage.CompetitionEntry>()).AsQueryable();
}
}
}
public DataAccess.Model.Competition ConvertToCompetition(DataAccess.Storage.Competition comp)
{
DataAccess.Model.Competition modelComp = new DataAccess.Model.Competition
{
CompetitionID = comp.CompetitionID,
Active = comp.Active,
CompetitionStatusID =
comp.CompetitionStatusID,
Duration = comp.Duration,
EndDate = comp.EndDate,
Entrants = comp.Entrants,
Featured = comp.Featured,
Image = comp.Image,
IsOvertime = comp.IsOvertime,
MaxEntrants = comp.MaxEntrants,
Notes = comp.Notes,
OvertimeDuration = comp.OvertimeDuration,
OvertimeEnd = comp.OvertimeEnd,
OvertimeStart = comp.OvertimeStart,
ParentCompetitionID = comp.ParentCompetitionID,
Prize = comp.Prize, StartDate = comp.StartDate,
SuggestedBy = comp.SuggestedBy,
Summary = comp.Summary,
Title = comp.Title
};
return modelComp;
}
public IEnumerable<DataAccess.Model.Competition> ConvertToCompetitionList(IEnumerable<DataAccess.Storage.Competition> compList)
{
List<DataAccess.Model.Competition> compModelList = new List<DataAccess.Model.Competition>();
foreach (DataAccess.Storage.Competition comp in compList)
{
compModelList.Add(ConvertToCompetition(comp));
}
return compModelList;
}
}
Agree with the comment on design principles by Adrian, but if you want to do it this way
public IQueryable<T> QueryableEntities
{
get
{
if (typeof(T).Equals(typeof(Model.Competition)))
{
return this.ConvertToCompetitionList(
this.GetTable<Storage.Competition>()).AsQueryable() as IQueryable<T>;
}
else if(typeof(T).Equals(typeof(Model.Submission)))
{
return this.ConvertToSubmissionList(
this.GetTable<Storage.CompetitionEntry>()).AsQueryable() as IQueryable<T>;
}
}
}
will compile and run fine. Here the x as IQueryable<T> gives x cast to IQueryable<T> if it can be cast and null if it can't.
Note: this means that when you construct your generic class if it has type Model.Competition it will return IQueryable<Model.Competition>, if it has type Model.Submission it will return IQueryable<Model.Submission>, and will return null for any other type.
It's usually best not to generalise. Lots of developers seem to spend a lot of time trying to make one property/method/class do many things, but it goes against lots of Object Oriented principles. Personally I would just use 2 properties, maybe called Competitions and the other Submissions. It'd be a lot more intention revealing than QueryableEntities.