|
BillWoodruff wrote: why does C# let me get away with this
Doesn't java and C++ allow the same thing?
Certainly in terms of identifier resolution I wouldn't expect anything else.
|
|
|
|
|
thanks, interesting, I have not used Java or C++ IDE's.
i do struggle with both "loving" C#, and wishing it was even more build-time "strongly typed" ... PostSharp is an example of how strong-typing can be extended via Attributes... of course, PostSharp is rewriting IL code post compilation, and what it does is fiendlishly complex ... and using it is complex.
for me, seeing duplicate top level field/property/method/whatever names is a red flag: of course, i see no flags with reuse of names for local trivial reasons, like i/j/k for for-loops.
for me, using ReSharper (been using it many years) does provide some critical support.
«The mind is not a vessel to be filled but a fire to be kindled» Plutarch
|
|
|
|
|
From memory, I believe Java defaults to virtual methods - so unless you specifically tell it not to, the method in the derived class will be called. This increase the risk of breaking changes simply by updating a package you depend on. If the base happens to have added a method you also have (not that unheard of as you might have overwritten to add a feature the library author is also working on), then your code will execute to the surprise of both of you. In C# with default implementation both the base class and the derived class will execute the same code they did before the update if no other code change is made.
|
|
|
|
|
lmoelleb wrote: I believe Java defaults to virtual methods
Correct.
|
|
|
|
|
How to save ImageAnnotation in the sample Solution I downloads it.the sample have only add and delete.
Thanks
|
|
|
|
|
Ask the person who created the download. We cannot guess what you are referring to.
|
|
|
|
|
Don't post this under Quick Answers - if you got the code from an article, then there is a "Add a Comment or Question" button at the bottom of that article, which causes an email to be sent to the author. They are then alerted that you wish to speak to them.
Posting this here relies on them "dropping by" and realising it is for them.
"I have no idea what I did, but I'm taking full credit for it." - ThisOldTony
"Common sense is so rare these days, it should be classified as a super power" - Random T-shirt
AntiTwitter: @DalekDave is now a follower!
|
|
|
|
|
gentle reminder: this forum is/was a language discussion forum; i ain't complaining, by saying that, that i think it being, now, more of a C# QA for grown-ups is a "bad thang"
the new .NET kid: [^] ... looks promising ... if (?) ...
you are remembering, as i do, the yogic contortions necessary for numeric Type conversions, the many different facilities from reflection, to 'ChangeType, etc.
and, the not=quite=-there weirdness necessary to try to constrain a generic parameter to a Numeric Type.
Scott Hanselman waxed eloquent on this in 2003: [^].
Okay ... the question is: have you tried/evaluated Math.Generics ?
And, what do you think ?
from the somewhat sidelined fossil, bill
«The mind is not a vessel to be filled but a fire to be kindled» Plutarch
|
|
|
|
|
I hadn't really used it yet (which may indicate something as well) but I briefly tried it just now, so keep in mind I don't really know my way around the API yet:
- Large repertoire of available operations, which applies to .NET 7 broadly, not only generic math. Nice operations such as rotates, popcount, leading zero count, are no longer hidden away in weird corners of the language (or worse: absent - as they used to be).
- Despite shift counts no longer needing to be
int , shifting by T is not allowed. So while working with T , shifting by constants is fine (since they'd be int ), but as soon as you want to shift by some value that comes out of a generic calculation.. well you still end up with some weird conversions. This also applies to the count parameter of rotates. This has anti-synergy with the return types of T.PopCount and T.TrailingZeroCount and so on, which return T . I definitely would want to write x >>> T.TrailingZeroCount(x) at some point, but no. - There is an explicit unsigned right shift, but
>> means "either signed or unsigned right shift depending on the type". What if I want an explicit signed right shift, even if T is an unsigned type? E: in non-generic code of course the answer is "just cast to the corresponding signed type, shift, then cast back". But then in generic code the question is, what type is that? See one of the next points for the problem with that. - There is no easy way to get the number of bits in
T . There are ways, sure, but I was hoping for T.BitSize or something like that. Do I really need to write T.PopCount(T.AllBitsSet) ? Bonus: the result of that is a T but you probably want an int . Or x.GetByteCount() * 8 perhaps? (why do I need an instance x to find the byte count?) - There seems to be no way to express certain constraints on types such as "given some signed type
TS , TU is the corresponding unsigned type of the same size". Well, I don't know how C# would do that. But I can do it in C++, and it would be useful. For example if I wanted to define a type-changing version of Abs , which takes a signed integer and returns an unsigned integer of the same size - as it is, I wouldn't be able to constrain the types to have the same size. As far as I know, anyway. - There are standard "low multiplications" that take two
T and return the low half of the product as a T . Elsewhere in .NET classes, there are functions such as Math.BigMul that return the full product. Generic T has a lot of fancy operations defined for it, but not BigMul (nor a hypothetical HighMul that only returns the upper half of the product).
Well it seems useful overall, but with some annoyances.
E: a sneaky advantage of generic math is that it lets you negate unsigned integers (ie find their additive inverse) with a plain old negation, no nonsense such as 0 - x . Progress! You still can't write -someUlong in non-generic code though.
modified 14-Jan-23 1:46am.
|
|
|
|
|
BillWoodruff wrote: And, what do you think ?
I think that if one has a lot of code that requires that one become familiar with that a lot then one of the following is true.
1. One is creating a mathematics library. Some advanced product, such as a matrix library
2. The code is wrong and someone is trying to be clever which will lead to increased maintenance costs.
|
|
|
|
|
I have a C# control application that communicates via USB (it shows up as a Com port in the Device Manager, but the electrical interface is USB, not RS232) with a development board with a microcontroller from ST Microelectronics (the driver I use is automatically installed by Windows 10 or Windows 11). Sometimes I need to debug and single-step the microcontroller and when I do, the C# application freezes for a long time and then usually eventually crashes when the Com port finally disappears and my Com connection is lost. Is there anything I can do to handle this a little more gracefully? It would be great if the Com port connection could simply get disconnected (instead of freezing the application) and the Com port disappears and then it could try to reconnect every second, in case the single-stepping has stopped and the microcontroller is running normally again. I'm programming in .NET 2.0 and I communicate using the System.IO.Ports.SerialPort class.
|
|
|
|
|
If you start "locking up" the device, then the app needs to be able to make async calls and perform the associated error handling. Otherwise, it "freezes".
"Before entering on an understanding, I have meditated for a long time, and have foreseen what might happen. It is not genius which reveals to me suddenly, secretly, what I have to say or to do in a circumstance unexpected by other people; it is reflection, it is meditation." - Napoleon I
|
|
|
|
|
I want to develop a C# console app that interacts with web page user provide it.
i.e; If i have a column on my webpage where the user have to set (tick/cross) sign.
I want that my C# app fill that whole column automatically according to data I provide it.
Kindly recommend me methods for this problem.
|
|
|
|
|
I doubt you are going to be able to do that without writing an extension for each browser and getting the user to install the appropriate one for their usage.
"I have no idea what I did, but I'm taking full credit for it." - ThisOldTony
"Common sense is so rare these days, it should be classified as a super power" - Random T-shirt
AntiTwitter: @DalekDave is now a follower!
|
|
|
|
|
Appreciate your response.
Sir, what solution you recommend for this?
|
|
|
|
|
Since I have no idea why you are trying to do this, I can't really suggest anything concrete at this point.
"I have no idea what I did, but I'm taking full credit for it." - ThisOldTony
"Common sense is so rare these days, it should be classified as a super power" - Random T-shirt
AntiTwitter: @DalekDave is now a follower!
|
|
|
|
|
|
If you want to automate a web browser from a desktop application, then you'll need to use a tool designed to do that - for example, Selenium[^].
Alternatively, you could use a tool such as Power Automate[^] to automate your interaction with the site. That has extensions for the three main browsers, as well as the now-deceased Internet Explorer: Automate webpages - Power Automate | Microsoft Learn[^]
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
I work with many Com-ports and to make them easier to keep track of I've created a combobox that has a fixed prefix (the information from the Device Manager, e.g. "STMicroelectronics STLink Virtual COM Port (COM21)") and an editable suffix where I can type in e.g. "My Product A". The code works great, but now I would like to also be able to disable (make the text gray) items in my combobox and it works fine in the dropdown list, but as soon as I close the dropdown list and only the selected item is shown, then the text is always enabled (black, not gray). Does anybody know what I should correct in my code to get the desired behavior?
partial class SemiEditableComboBox
{
private System.ComponentModel.IContainer components = null;
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Component Designer generated code
private void InitializeComponent()
{
this.comboBox = new System.Windows.Forms.ComboBox();
this.SuspendLayout();
this.comboBox.FormattingEnabled = true;
this.comboBox.Location = new System.Drawing.Point(0, 0);
this.comboBox.Name = "comboBox";
this.comboBox.Size = new System.Drawing.Size(454, 24);
this.comboBox.TabIndex = 0;
this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 16F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.Controls.Add(this.comboBox);
this.Name = "SemiEditableComboBox";
this.Size = new System.Drawing.Size(454, 24);
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.ComboBox comboBox;
}
public delegate void DelegateItemAndString(object item, string newString);
class SemiEditableComboBoxItem
{
public string lastString;
public string fixedPrefix;
public DelegateItemAndString editableSuffixChanged;
public bool enabled;
public SemiEditableComboBoxItem(string lastString, string fixedPrefix, DelegateItemAndString editableSuffixChanged, bool enabled)
{
this.lastString = lastString;
this.fixedPrefix = fixedPrefix;
this.editableSuffixChanged = editableSuffixChanged;
this.enabled = enabled;
}
}
public partial class SemiEditableComboBox : UserControl
{
private volatile bool modifySelection = false;
private int currentlySelectedIndex;
private List<SemiEditableComboBoxItem> items;
public event EventHandler SelectedIndexChanged;
public SemiEditableComboBox()
{
Font = new Font(Font.Name, 8.25f * 96f / CreateGraphics().DpiX, Font.Style, Font.Unit, Font.GdiCharSet, Font.GdiVerticalFont);
InitializeComponent();
this.comboBox.Width = this.Width;
this.comboBox.Height = this.Height;
items = new List<SemiEditableComboBoxItem>();
this.Resize += new EventHandler(delegate(object sender, EventArgs e)
{
this.comboBox.Width = this.Width;
this.comboBox.Height = this.Height;
});
this.comboBox.SelectedIndexChanged += new EventHandler(comboBox_SelectedIndexChanged);
this.comboBox.TextChanged += new EventHandler(comboBox_TextChanged);
this.comboBox.DrawMode = DrawMode.OwnerDrawFixed;
this.comboBox.DrawItem += comboBox_DrawItem;
}
protected override void OnPaint(PaintEventArgs e)
{
if (modifySelection)
{
modifySelection = false;
if ((comboBox != null) && (currentlySelectedIndex < items.Count) &&
(items[currentlySelectedIndex] != null) &&
(!string.IsNullOrEmpty(items[currentlySelectedIndex].fixedPrefix)))
{
comboBox.SelectionStart = items[currentlySelectedIndex].fixedPrefix.Length;
comboBox.SelectionLength = 200;
}
}
}
private void comboBox_DrawItem(object sender, DrawItemEventArgs ea)
{
ea.DrawBackground();
ea.DrawFocusRectangle();
Rectangle bounds = ea.Bounds;
bool enableItem = (ea.Index < 0) ? false : ((SemiEditableComboBoxItem)items[ea.Index]).enabled;
Font myFont = new Font(ea.Font, FontStyle.Italic);
if (ea.Index != -1)
{
ea.Graphics.DrawString(comboBox.Items[ea.Index].ToString(), ea.Font, new SolidBrush(enableItem ? Color.Black : Color.Gray), bounds.Left, bounds.Top);
}
else
{
ea.Graphics.DrawString(Text, ea.Font, new SolidBrush(Color.Gray), bounds.Left, bounds.Top);
}
}
private void comboBox_SelectedIndexChanged(object sender, EventArgs e)
{
currentlySelectedIndex = this.comboBox.SelectedIndex;
if (SelectedIndexChanged != null)
{
SelectedIndexChanged(sender, e);
}
modifySelection = true;
this.Invalidate();
}
private void comboBox_TextChanged(object sender, EventArgs e)
{
int selectedIndex = comboBox.SelectedIndex;
if (0 <= selectedIndex)
{
currentlySelectedIndex = selectedIndex;
}
if (items[currentlySelectedIndex].editableSuffixChanged == null)
{
this.comboBox.TextChanged -= new EventHandler(comboBox_TextChanged);
comboBox.Text = items[currentlySelectedIndex].lastString;
this.comboBox.TextChanged += new EventHandler(comboBox_TextChanged);
return;
}
else if (this.comboBox.Text.StartsWith(items[currentlySelectedIndex].fixedPrefix))
{
items[currentlySelectedIndex].lastString = comboBox.Text;
}
else
{
this.comboBox.TextChanged -= new EventHandler(comboBox_TextChanged);
comboBox.Text = items[currentlySelectedIndex].lastString;
this.comboBox.TextChanged += new EventHandler(comboBox_TextChanged);
}
if (!this.comboBox.Items[currentlySelectedIndex].ToString().Equals(items[currentlySelectedIndex].lastString))
{
this.comboBox.TextChanged -= new EventHandler(comboBox_TextChanged);
this.comboBox.DrawMode = DrawMode.OwnerDrawFixed;
if (items[currentlySelectedIndex].editableSuffixChanged != null)
{
items[currentlySelectedIndex].editableSuffixChanged(comboBox.Items[currentlySelectedIndex], items[currentlySelectedIndex].lastString.Substring(items[currentlySelectedIndex].fixedPrefix.Length));
}
this.comboBox.DrawMode = DrawMode.Normal;
this.comboBox.DrawMode = DrawMode.OwnerDrawFixed;
this.comboBox.TextChanged += new EventHandler(comboBox_TextChanged);
}
comboBox.SelectionStart = items[currentlySelectedIndex].lastString.Length;
comboBox.SelectionLength = 0;
}
public void addItem(object item, string initialText, string fixedPrefix, DelegateItemAndString editableSuffixChanged)
{
addItem(item, initialText, fixedPrefix, editableSuffixChanged, false);
}
public void addItem(object item, string initialText, string fixedPrefix, DelegateItemAndString editableSuffixChanged, bool enabled)
{
comboBox.Items.Add(item);
items.Add(new SemiEditableComboBoxItem(initialText, fixedPrefix, editableSuffixChanged, enabled));
}
public int itemsCount
{
get
{
return comboBox.Items.Count;
}
}
public void setItemEnabled(int index, bool enabledOrDisabled)
{
items[index].enabled = enabledOrDisabled;
}
public bool getItemEnabled(int index)
{
return items[index].enabled;
}
public void clearAllItems()
{
comboBox.Items.Clear();
items.Clear();
}
public int selectedIndex
{
get
{
return currentlySelectedIndex;
}
set
{
this.comboBox.SelectedIndexChanged -= new EventHandler(comboBox_SelectedIndexChanged);
comboBox.SelectedIndex = value;
modifySelection = true;
this.Invalidate();
this.comboBox.SelectedIndexChanged += new EventHandler(comboBox_SelectedIndexChanged);
}
}
public object selectedItem
{
get
{
return comboBox.Items[selectedIndex];
}
}
public object getItem(int index)
{
return comboBox.Items[index];
}
public DrawMode drawMode
{
set
{
this.comboBox.DrawMode = value;
}
}
}
|
|
|
|
|
You manually draw the items yourself in the comboBox_DrawItem event handler - and that means you select the Brush in which they are drawn. In order to "grey out" selections, you'd need to change the enable code you have there.
"I have no idea what I did, but I'm taking full credit for it." - ThisOldTony
"Common sense is so rare these days, it should be classified as a super power" - Random T-shirt
AntiTwitter: @DalekDave is now a follower!
|
|
|
|
|
I'm not sure I understand what you mean. Even if I do a global replace Color.Black -> Color.Gray then the selected item still has black color, not gray, when the dropdown list isn't shown.
|
|
|
|
|
are you sure that enableItem is really false when DrawItem is called ?
|
|
|
|
|
I added Debug.WriteLine(enableItem ? "Enabled" : "Disabled"); inside comboBox_DrawItem and it always prints "Disabled".
|
|
|
|
|
another try :
I would assign the color depending on the enableItem outside the DrawString-call.
Use this variable for DrawString and also for Debug.WriteLine.
In the Moment I can't see a mistake ...
|
|
|
|
|
So, the DrawItem event is used to draw the items that appear in the dropdown list and not the actual selected value. The colour of the selected text is set by ForeColor . It seems to me that the simple solution would be to change the ForeColor , depending on whether the selection was enabled or not. Something like this:
private void comboBox_TextChanged(object sender, EventArgs e)
{
bool enableItem = (SelectedIndex < 0) ? false : comboBox.Items[SelectedIndex]).enabled;
comboBox.ForeColor = enableItem ? Color.Black : Color.Gray;
}
|
|
|
|
|