|
I see that I got that point backwards. Sorry, I'm still assimilating a lot of information from the other answers to this question, some of which seem to boil down to personal preference.
I think that I am getting the point. The usage of out is to give the programmer more than one way to approach functions that can/will fail in predetermined ways and to provide the programmer with choices on how to handle them. If one prefers, they can handle an exception from Convert.ToInt32(object) or respond to a false return of Int32.TryParse(object, out int) . Additionally, this can or cannot be applicable given the code's context and task. Still, both methods seem equally fine to me.
if (Object.DividedByZero == true) { Universe.Implode(); }
Meus ratio ex fortis machina. Simplicitatis de formae ac munus. -Foothill, 2016
|
|
|
|
|
Not just that, but yes.
The Exceptions part is just an example - there are load of other cases where you might want to use an out , but they are harder to explain in isolation.
For example, you might want to split out certain values from a collection and return the number of them:
private int GetForSomeReason(List<MyClass> mc, out List<MyClass> result, string somethingToLookFor)
{
... That way, you can chain them together:
int total = GetForSomeReason(myList, out listOfJoes, "joe") + GetForSomeReason(myList, out listOfMikes, "mike"); (I'm not suggesting that that's a good design, just a trivial example of a complicated scenario)
Bad command or file name. Bad, bad command! Sit! Stay! Staaaay...
|
|
|
|
|
I can see that there are cases when out would make sense when it would save time later in program execution if the same information gathered in one function will be needed by another function in the event that the correct conditions are satisfied.
if (Object.DividedByZero == true) { Universe.Implode(); }
Meus ratio ex fortis machina. Simplicitatis de formae ac munus. -Foothill, 2016
|
|
|
|
|
As in everything else, it really depends what you are trying to solve. I have seen many contorted solutions to avoiding the use of out parameters and whether or not they make sense really depends on what the intent of the code was. Let's take the Try... routines. With later versions of the .NET framework, what could the API designers do? One option is to use a class structure that looks something like this:
public class Parse<T>
{
public bool HasValue;
public T Value;
} This could then be the target of something like this:
Parse<int> value = int.TryParse("12");
if (!value.HasValue) return;
DoSomething(value.Value); While this may seem to be a reasonable solution, on the surface, there are several issues with this design. The biggest problem I have with it is that you are allocating a larger object than you need to. Even if we were to change this to a struct, it's still an unreasonably large surface area for a simple value. Another problem is the cumbersome syntax of having to use value.Value to get the value - you could use implicit operators to work around this but that's adding extra burden again. Granted, the language could be extended with syntactic sugar to hide the underlying implementation (much like null operator hiding the underlying Nullable<T> implementations) but this is, again, overkill because Nullable types were added to support a real problem in the codebase.
So, what other options have I seen? Well, I have seen people returning a tuple with the first parameter being the success or not of the operation. I have seen people advocating the use of exceptions - thereby largely missing the point and I have seen delegates in various forms being required to set values. I have also seen APIs that require multiple calls, the first being a CanParse (or whatever command you need here), followed by a Parse - this being a particularly daft operation because you are effectively calling parse twice - the first one being required to see if you can parse the value, and then the second one being called to get the same value out that you would have got out with the previous operation.
This space for rent
|
|
|
|
|
Pete O'Hanlon wrote: While this may seem to be a reasonable solution, on the surface, there are several issues with this design. The biggest problem I have with it is that you are allocating a larger object than you need to. Even if we were to change this to a struct, it's still an unreasonably large surface area for a simple value.
I'm having some trouble grasping the rationale here, mostly due to the "unreasonably" part. I'm hard-pressed to quantify an extra bit value as unreasonable, especially since it's bundled with a possibly null value and enables an almost English-language null-check mechanism.
After all, the Tuple solution will result in the same memory reservation with the same ubiquitous value access (though I find variable.Item2 less useful than variable.Value).
The exception solution potentially breaks the "don't use exceptions for flow control" rule, which is one of those rules that actually makes objective sense.
I suppose you could use an event driven parser instead, but that introduces even more code overhead.
Now that I think about it, that might be worth working up to add to my library, thanks for the idea!
"There are three kinds of lies: lies, damned lies and statistics."
- Benjamin Disraeli
|
|
|
|
|
It's worth noting that I'm not recommending the Tuple approach either. Basically, what I'm talking about is the fact that you are potentially allocating a class here (if you define this as a class) that will be created on the stack, rather than being on the heap for a reference type. And remember that the boolean return value is going to exist for longer than it needs to if you define your Parse class/struct as a member variable.
This space for rent
|
|
|
|
|
Absolutely understood on the Tuple part. What I saw was what you perceived to be a collection of "bad" ideas.
In terms of cost, though, I've just always seen the intrinsic resilience value of the wrapper class to considerably outweigh the cost of having an extra bit floating around for a GC cycle. Even in aggregate, it would take a massive dataset being processed through a poorly-devised pipeline (after all, how hard is "variable.HasValue ? yield variable.Value : continue"?) in order for that to even show as a blip on the radar.
I suppose I'm mostly curious about a different point of view, mainly how the cost-benefit analysis works
"There are three kinds of lies: lies, damned lies and statistics."
- Benjamin Disraeli
|
|
|
|
|
The key part was my first sentence that it all depends on the context. My point there was that there are times when it's simpler and more appropriate to just return an "out" value, rather than having to contort yourself for the sake of purism. I deliberately focused on the OP's sample because the Try.... don't really need to do much more than they do. Now, suppose we wanted to extend the example, what about if we were looking to answer the question of why did it fail? Then it becomes more appropriate to return a struct/class.
public class Parse<T>
{
bool HasValue { get; set; }
T Value { get; set; }
string AdditionalInformation { get; set; }
}
This space for rent
|
|
|
|
|
Thank you for the level of detail in your posts. If I may, I will attempt to extrapolate some meaning. What I am think I am understanding is that, as one is writing code, the coder should use a minimalist approach first, only writing what is necessary. When the problem cannot be solved or the task completed and still have the code make sense when it's done, then that is when some of the more advanced (I use that term loosely here as pointers are nothing new) features of the C# language that could simplify what might otherwise have a bit of a learning curve. Is this at all similar to what you are implying?
if (Object.DividedByZero == true) { Universe.Implode(); }
Meus ratio ex fortis machina. Simplicitatis de formae ac munus. -Foothill, 2016
|
|
|
|
|
You could always use nested classes to (somewhat) avoid the extra storage:
public abstract class Parse<T>
{
public abstract bool HasValue { get; }
public abstract T Value { get; }
public abstract string AdditionalInformation { get; }
private sealed class ParseSome : Parse<T>
{
public ParseSome(T value)
{
Value = value;
}
public override bool HasValue => true;
public override string AdditionalInformation => null;
public override T Value { get; }
}
private sealed class ParseNone : Parse<T>
{
public ParseNone(string additionalInformation)
{
AdditionalInformation = additionalInformation;
}
public override bool HasValue => false;
public override string AdditionalInformation { get; }
public override T Value
{
get { throw new InvalidOperationException(AdditionalInformation); }
}
}
public static Parse<T> Some(T value)
{
return new ParseSome(value);
}
public static Parse<T> None(string additionalInformation)
{
return new ParseNone(additionalInformation);
}
}
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
Not a hard-and-fast rule, but I have often found that if I need an out or ref parameter, it indicates that my object model might be wrong.
Of course, it's not always easy, or possible, to get that entirely as you would like it, due to the interfaces that need to be used.
However, as perhaps a poor example (since you admit your example isn't the best), instead of:
public bool IsProductOnSale(guid productId, out Guid[] productResellerIds)
{
}
maybe you would consider having "Product" objects, instead of using a raw id. This could then contain all the information you need, and/or look it up as-and-when required:
e.g:
class Product
{
private Collection<Seller> resellers;
public Collection<Seller> Resellers
{
if (null == resellers)
{
}
return resellers;
}
public bool IsProductOnSale()
{
return (Resellers.Count > 0);
}
}
Then you could do
if (myProduct.IsProductOnSale) { foreach (Seller in myProduct.Resellers) { ... }
without obtaining the information from the database twice. Your calling code doesn't even need to know how (or when) the information is retrieved - you might decide to do it in the constructor.
Your constructor for Product would probably take a guid... etc, etc.
|
|
|
|
|
Thanks for the input. I have classes similar to your Product , which wrap up data from a database into an object to be used by other functions. With my example, the idea I was working with is that here is a function that connects to the database and retrieves data that can change any time (e.g. Product). I also have data that changes infrequently and can be kept in memory and is periodically refreshed (e.g. Reseller). Would it make sense to fetch a result set of variable data and use the out parameter to contain related persistent data that you already have? Or would it be better to break this into two or three other functions for each step?
if (Object.DividedByZero == true) { Universe.Implode(); }
Meus ratio ex fortis machina. Simplicitatis de formae ac munus. -Foothill, 2016
|
|
|
|
|
I have a simple winform (C#) with a text box and a button.
My requirement is that while the button is clicked the text box content should be added with "Some message". As long the button is in clicked status the message in text box should be kept on adding.
The moment I let go the button (remove my finger off the mouse), this adding message to text box should stop.
Is there a while clicked loop possible in a button click event ?
|
|
|
|
|
Timer, set to 10ms interval
Set the text box text based on whether the button is clicked currently
|
|
|
|
|
Do you want to keep the message posted when there is button pressed, as soon as you release the button it should stop posting right ?
The click event will not help you anymore here, cause click is the combination of 'keyPress' and 'keyUp' event
you need to handle both events, on 'keyPress' post the message in textbox and on 'keyUp' event stop posting
hope it helps
Find More .Net development tips at : .NET Tips
The only reason people get lost in thought is because it's unfamiliar territory.
|
|
|
|
|
Don't you mean MouseDown and MouseUp?
|
|
|
|
|
Oooops big typo.
Yes, I mean MouseUp and Down event with timer will accomplish his task
Find More .Net development tips at : .NET Tips
The only reason people get lost in thought is because it's unfamiliar territory.
|
|
|
|
|
Don't use a Timer. Use the methods on the Button MouseDown to start the update and MouseUp to stop the update.
You should probably do the updating on a separate Thread ... this CodeProject article can be adapted to do what you want - Simple Threading[^]
For example I have a button btnDemo - when I hold it "down" with my mouse a label lblDemo will get a number displayed. When I release the button then the label will get the text "stopped"...
Here is the code that handles the mouseclicks on the button
private void btnDemo_MouseDown(object sender, MouseEventArgs e)
{
demoThread = new Thread(ThreadProcSafe);
btnDemo.Text = "Stop Demo";
demoThread.Start();
}
private void btnDemo_MouseUp(object sender, MouseEventArgs e)
{
if (!stopDemo)
{
stopDemo = true;
if (!demoThread.Join(1000))
{
demoThread.Abort();
}
SetText("Stopped");
btnDemo.Text = "Start Demo";
}
} And here is the code that actually sets up the thread and SetText functons (with some very basic error handling). These are the bits you need to change to put your message in your TextBox
delegate void SetTextCallback(string text);
private Thread demoThread;
private volatile bool stopDemo;
private void ThreadProcSafe()
{
var x = 0;
while (!stopDemo)
{
SetText((x++).ToString());
Thread.Sleep(600);
}
}
private void SetText(string text)
{
try
{
if (lbl_right.Disposing) return;
if (lblDemo.InvokeRequired)
{
var d = new SetTextCallback(SetText);
BeginInvoke(d, text);
}
else
lblDemo.Text = text;
}
catch (Exception e)
{
MessageBox.Show(e.Message);
}
}
If you read the article it points out that sometimes the threads won't close properly when you attempt to close the application. Because we have the thread starting on a mouse down and ending on the mouse-up this is less likely but still worth adding this method into the form -
protected override void OnClosed(EventArgs e)
{
stopDemo = true;
if (!demoThread.Join(1000))
{
demoThread.Abort();
}
base.OnClosed(e);
}
|
|
|
|
|
Fantastic CHill60.
Thank you ! Your tip works like a miracle. !!
Cheers !!
|
|
|
|
|
Wish I could claim the credit - if that article by loneferret helped you then be sure to give it an up-vote
|
|
|
|
|
|
I am updating my all in one IServiceProvider IoC container.
Previously I was only accessing public type, public constructors, public properties.
Now I am also checking private stuff.
Now when I run my console app.
Assembly a;
a.DefinedTypes
Work fine and I can enumerate them and instantiate them. Whether or not they are private type.
But I suspect there are circumstance where this utility class won't be working.. In fact my .NET security is... tenuous... but you could reduce the right of a piece of code...
How to check whether or not I can do those private reflective operation or not?!
When Can't I do them?
|
|
|
|
|
Im very new to C# and am trying to use conversion tools to change some VB over. Im not quite sure how to remedy this error, so any help I can get is greatly appreciated!
This is the error Im receiving:
"CS0266: Cannot implicitly convert type 'System.Web.UI.Control' to 'System.Web.UI.WebControls.LinkButton'. An explicit conversion exists (are you missing a cast?)"
for Line 93
myDeleteButton = myTableCell.Controls[0];
Here is the full C# code:
public void Page_Load(object Source, EventArgs E)
{
if (!Page.IsPostBack)
{
BindData();
}
}
public void BindData()
{
DataSet myDataSet = new DataSet();
SqlDataAdapter mySqlDataAdapter = default(SqlDataAdapter);
mySqlDataAdapter = new SqlDataAdapter("SELECT * FROM glmaster", "REMOVED;");
mySqlDataAdapter.Fill(myDataSet, "glmaster");
glmasterInfo.DataSource = myDataSet.Tables["glmaster"];
glmasterInfo.DataBind();
}
public void DataGrid_Delete(object Source, DataGridCommandEventArgs E)
{
SqlConnection myConnection = default(SqlConnection);
SqlCommand myCommand = default(SqlCommand);
string strDeleteStmt = "";
decimal balance_test = new decimal();
string Balance_output = "";
balance_test = System.Convert.ToDecimal(Convert.ToDecimal(E.Item.Cells[6].Text));
if (balance_test == 0.0M)
{
outError.InnerHtml = "";
strDeleteStmt = "DELETE FROM glmaster " +
" WHERE major = " + E.Item.Cells[1].Text +
" AND minor = " + E.Item.Cells[2].Text +
" AND sub1 = " + E.Item.Cells[3].Text +
" AND sub2 = " + E.Item.Cells[4].Text;
try
{
myConnection = new SqlConnection(
"REMOVED;");
myCommand = new SqlCommand(strDeleteStmt, myConnection);
myConnection.Open();
myCommand.ExecuteNonQuery();
glmasterInfo.EditItemIndex = -1;
BindData();
}
catch (Exception exc)
{
outError.InnerHtml = "* Error while deleting data.<br />"
+ exc.Message + "<br />" + exc.Source;
}
finally
{
myConnection.Close();
}
}
else
{
Balance_output = balance_test.ToString("C");
string Error_String = "";
Error_String = "<center>You Can\'t Delete This Account<br>";
Error_String = Error_String + "Balance is NOT zero.<br>";
Error_String = Error_String + "The Account Balance is " + Balance_output;
Error_String = Error_String + " for ";
Error_String = Error_String + E.Item.Cells[1].Text + "-";
Error_String = Error_String + E.Item.Cells[2].Text + "-";
Error_String = Error_String + E.Item.Cells[3].Text + "-";
Error_String = Error_String + E.Item.Cells[4].Text + "</center>";
outError.InnerHtml = Error_String;
}
}
public void DataGrid_ItemCreated(object Sender, DataGridItemEventArgs e)
{
if (((e.Item.ItemType == ListItemType.Item) || (e.Item.ItemType == ListItemType.AlternatingItem)) || (e.Item.ItemType == ListItemType.EditItem))
{
TableCell myTableCell = default(TableCell);
myTableCell = e.Item.Cells[0];
LinkButton myDeleteButton = default(LinkButton);
myDeleteButton = myTableCell.Controls[0];
myDeleteButton.Attributes.Add("onclick", "javascript: return confirm(\'Are you Sure you want to delete this account?\');");
}
}
modified 19-Apr-16 11:29am.
|
|
|
|
|
It would really help us to help you if you actually indicated (with a comment) where the error occurs.
|
|
|
|
|
sorry about that. Line 93
myDeleteButton = myTableCell.Controls[0];
|
|
|
|