|
At some point, once my understanding of XML is good enough that is, I can take off the training wheels and move over to Linq XML. I would like to gain a deeper knowledge of XML and how to manipulate it first before I do.
Still, I was so surprised that I found a use for the ref keyword that I had to share.
if (Object.DividedByZero == true) { Universe.Implode(); }
Meus ratio ex fortis machina. Simplicitatis de formae ac munus. -Foothill, 2016
|
|
|
|
|
The framework will not make a copy of the string when entering a new method; it is not a value-type, so no copy. It will create a new immutable once you manipulate it.
Bastard Programmer from Hell
If you can't read my code, try converting it here[^]
|
|
|
|
|
That's news to me. Do you happen to have a reference to that? I was operating on the assumption that immutable types are passed by copy and not by pointer, hence the need for ref so that it could be passed by pointer and replaced if necessary.
if (Object.DividedByZero == true) { Universe.Implode(); }
Meus ratio ex fortis machina. Simplicitatis de formae ac munus. -Foothill, 2016
|
|
|
|
|
I'll be googling for a reference after the groceries; I'm out of coffee and that's a priority.
I vaguely remember something about string.Clone that doesn't return a clone, because it is "immutable" and the string will only exist in memory once.
Bastard Programmer from Hell
If you can't read my code, try converting it here[^]
|
|
|
|
|
Coffee works miracles. Only "interned" strings are kept in memory in that way, and if your string doesn't come from a literal but from user-input, this doesn't happen automatic.
The string is still a reference-type, and its value 'should' not be duplicated as with a value-type. Passing it with the ref keyword means that you are modifying the data of supplied variable. Since the alternative does return a new immutable string, what you said makes sense
Bastard Programmer from Hell
If you can't read my code, try converting it here[^]
|
|
|
|
|
I agree with the previous commentator that for this specific case System.Xml.Linq is the best tried and true solution.
However, if we take a look at the broader case
Quote: If there is still a use for ref, it is with handling immutable types such as strings in functions where they may or may not be replaced with a new value.
then how about working with mutable type instead of immutable? i.e. StringBuilder[^]
|
|
|
|
|
Since I was building this to process inputs from users into an XML document and the statistically low incidence of invalid characters, StringBuilder was not the best option in this case. The data exists as a bunch of strings already and copying them all to a StringBuilder on the off chance they will be changed seemed wasteful. I wanted to combine the validation and replacement operations into a single step but without the need to create copies of a string in memory unnecessarily. The code itself is run-of-the-mill. I was just surprised to actually find a language-correct appllicaton for ref as I have never been able to put it to use before.
if (Object.DividedByZero == true) { Universe.Implode(); }
Meus ratio ex fortis machina. Simplicitatis de formae ac munus. -Foothill, 2016
|
|
|
|
|
Perhaps "ref" has more of a place when it comes to "inter-op".
It seems there is frequent use "ref" in C# when talking to MS Word, for example:
Globals.ThisDocument.CheckSpelling(
ref missing, ref ignoreUppercase, ref missing, ref missing, ref missing, ref missing,
ref missing, ref missing, ref missing, ref missing, ref missing, ref missing);
"(I) am amazed to see myself here rather than there ... now rather than then".
― Blaise Pascal
|
|
|
|
|
That's not so much of an issue since C# 4 was released. You can omit all of the ref missing arguments, and use named arguments for the ones you want to pass.
And I believe you may be able to omit the ref on the other arguments as well (for Interop calls only); but don't quote me on that.
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
That also makes sense. The MS documentation on ref is a little confusing since technically all objects are passed by reference (i.e. pointer). Since C# does everything it can to hide all the pointer shenanigans, I do believe it was tacked on to show that a method argument is being passed by pointer and highlight that the pointer passed to the method might not point to the same location when the function exits. Passing pointers around in C++ is common and I believe this was their way of representing it.
if (Object.DividedByZero == true) { Universe.Implode(); }
Meus ratio ex fortis machina. Simplicitatis de formae ac munus. -Foothill, 2016
|
|
|
|
|
The short answer is: "value types" (like int) are passed as / by "value". In order to "update the source", you need to pass them "by reference" via the "ref" keyword.
Another example is the "Interlocked" commands; which allow you to update "value type refs" (e.g. "counters") concurrently from multiple threads as atomic operations.
"(I) am amazed to see myself here rather than there ... now rather than then".
― Blaise Pascal
|
|
|
|
|
Foothill wrote: all objects are passed by reference
Slightly confusing two different things. Reference types are passed as references (pointers), but they are not passed "by ref".
You can update things in the reference that the parameter points to; but if you change the parameter to point to a different reference, that change won't be seen by the caller.
Adding ref (or out ) to the parameter means that, if you change it to point to something else, that change will be seen by the caller.
My C++ is terribly rusty, but I believe it's equivalent to passing either a * (by value) or a ** (by ref) parameter.
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
Richard Deeming wrote: I believe it's equivalent to passing either a * (by value) or a ** (by ref) parameter.
I don't really see it like that, but I may be wrong.
I see a pointer as a inherent array of values whose type is this of the pointer (a char* as an array of characters, for example).
I see a pointer to a pointer as a bidimensional array (a char** as an array of arrays of characters).
I like the possibility in C++ to specify the const-ness of either the value pointed to, or the const-ness of the pointer itself.
void func(const object* obj) allows to change the address to which obj is pointing, but not the value of the eventual members which obj could have.
void func(object* const obj) forbids to change the address to which obj is pointing, but allows to change the values of its eventual members.
void func(const object* const obj) forbids to change the address to which obj is pointing as well as any modification to object members.
In that sense, C++ is more versatile as it allows to control very precisely the mutability of the objects we are using. In C#, controlling the mutability of an object implies a lot more code and complexity.
Again, I am quite fresh in C++, so I may be wrong, or incomplete on the subject.
"I'm neither for nor against, on the contrary." John Middle
|
|
|
|
|
void ValidateForXml(ref string value) ... I do not like the idea so much, though it is syntactically correct. That function is meant to encode some data, so I'd declare it accordingly, i.e. with a return type:
string EncodeForXml(string input) : now its purpose is clear.
By the way, I'd look for some library for that purpose instead of trying to invent my own library - are you sure can enumerate all the special cases you have to take care of when doing it your self?
Oh sanctissimi Wilhelmus, Theodorus, et Fredericus!
|
|
|
|
|
Hi there,
DataGridView.CellValidatin works fine if all operations are done with keyboard. However, if the user has a mouse click on another cell, the focus goes to the new cell directly and the CellValidating event is never fired.
How to force cellValidating to fire (and keep the focus on the cell if the validation failed)? I googled a lot but could not find a solution to this problem.
Thanks in advance.
Mars Lam
-- modified 26-Feb-18 22:39pm.
|
|
|
|
|
public Form1()
{
InitializeComponent();
var d = new List<Tuple<string, int>>() {
new Tuple<string, int>("test1", 12),
new Tuple<string, int>("test2", 16),
new Tuple<string, int>("test3", 20)
};
dataGridView1.AutoGenerateColumns = true;
dataGridView1.EditMode = DataGridViewEditMode.EditOnKeystrokeOrF2;
dataGridView1.DataSource = d;
dataGridView1.CellValidating += dataGridView1_CellValidating;
}
void dataGridView1_CellValidating(object sender, DataGridViewCellValidatingEventArgs e)
{
e.Cancel = false;
MessageBox.Show(string.Format("CellValidating {0}, {1}", e.RowIndex, e.ColumnIndex));
}
Works as expected, and raises a CellValidating event each time you click outside the cell (even on closing the application).
Bastard Programmer from Hell
If you can't read my code, try converting it here[^]
|
|
|
|
|
Hi Eddy,
Thanks for the sample program, it works and helped me found the cause of my problem.
It was because I had the below line in .CellValidating event, for trouble shooting another problem long time ago.
if (this.ActiveControl.Equals(sender)) return;
After removing this line, the program works as expected.
Thank you very much for your help!
Mars Lam
|
|
|
|
|
You're welcome
Bastard Programmer from Hell
If you can't read my code, try converting it here[^]
|
|
|
|
|
Usually "row validation" at "save time" is sufficient.
If you are not careful, you can get into a deadlock when doing cross-edits at the field / cell level.
("Moving focus" in "forms" when necessary is simpler than in a grid).
"(I) am amazed to see myself here rather than there ... now rather than then".
― Blaise Pascal
|
|
|
|
|
I am trying to read bar code from barcode scanner device in Razor View textbox. But when i press scan button it opens the Bookmarks and put the barcode there, while focus is on textbox.
Please Help,
Thanks in Advance.
|
|
|
|
|
Check your scanner hardware setup: most come set up to act as a keyboard, but it's possible to set them to also add lead in / lead out characters to let you detect barcode input and direct it to a specific field. I'd suspect that the lead in or lead out setup has been configured to a sequence which opens the bookmarks in your browser.
See your manufacturer documentation or website for details, they are all different.
Bad command or file name. Bad, bad command! Sit! Stay! Staaaay...
AntiTwitter: @DalekDave is now a follower!
|
|
|
|
|
hi all,
i would like a loop for this.....
textBox10.Text = arr[0].ToString();
textBox11.Text = arr[1].ToString();
textBox12.Text = arr[2].ToString();
textBox13.Text = arr[3].ToString();
textBox14.Text = arr[4].ToString()
etc.....
is it possible?
thanx,
jim.
|
|
|
|
|
|
.... edit ...
Jim wrote:Member 13070736 wrote: that seems like way too much effort just to slot an array into textboxes. It is an effort If you clarify what you are doing further, there may be simpler ways: are you using a database here ? As I sai to Luc:Quote: The need for a collection of TextBox Controls functioning as a kind of logical unit for inputting/validating a set of data is very common. I prefer to implement this in a UserControl (or Panel) that implements validation, provides options for either sequential entry, random entry, etc. ... or, in a Form shown as a Dialog. ... end edit ...
Sure, it's possible: there are several different ways. A key factor in choosing how to implement this is whether the values in your list will change, or, remain fixed.
Assuming they change, this is one technique:
using System;
using System.Collections.Specialized;
using System.Windows.Forms;
using System.Collections.ObjectModel;
namespace YourNameSpace
{
public class MapIntsToTextBoxes : ObservableCollection<int>
{
public MapIntsToTextBoxes(params int[] ints)
{
foreach (int i in ints)
{
this.Add(i);
}
}
}
} Here's a usage example:
using System;
using System.Collections.Specialized;
using System.Windows.Forms;
using YourNameSpace;
namespace YourWinFormProject
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private List<TextBox> TBoxes = new List<TBoxes>{
textBox10,
textBox11,
textBox12,
textBox13,
textBox14
};
private MapIntsToTextBoxes mapper = new MapIntsToTextBoxes(1,2,3,4,5);
private void Form1_Load(object sender, System.EventArgs e)
{
mapper.CollectionChanged += MapperOnCollectionChanged;
mapper[3] = 1000;
}
private void MapperOnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
switch (e.Action)
{
case NotifyCollectionChangedAction.Replace:
TBoxes[e.OldStartingIndex].Text = e.NewItems[0].ToString();
break;
case NotifyCollectionChangedAction.Add:
break;
case NotifyCollectionChangedAction.Remove:
break;
case NotifyCollectionChangedAction.Move:
break;
case NotifyCollectionChangedAction.Reset:
break;
}
}
}
} There's a potential problem with this: if you expose an Observable Collection, remember that there's no way to cancel the other Actions, like Add, Remove. You can find some work-arounds for this, but, imho, they are complex.
And, there are other ways of achieving this including binding, but,in Win Forms, thee binding facility ... inferior to WPF, imho ... is something I avoid based on difficulties I've had with it: but, hey, it might work for you.
«... thank the gods that they have made you superior to those events which they have not placed within your own control, rendered you accountable for that only which is within you own control For what, then, have they made you responsible? For that which is alone in your own power—a right use of things as they appear.» Discourses of Epictetus Book I:12
modified 26-Feb-18 5:28am.
|
|
|
|
|
I have two comments:
1. Controls, just like all variables, deserve a descriptive name; if they are too many to come up with decent names, you're not on the right track.
2. When your user interface requires a large number of Controls you probably should rethink your design, there are bound to be better ways to handle things. Maybe what you need here is a DataGridView with a TextBox column i.e. a DataGridViewTextBoxColumn[^]. And obviously a DGV offers a Rows collection which you can easily enumerate.
modified 25-Feb-18 18:39pm.
|
|
|
|
|