|
|
|
This is a followup to a thread started in the Lounge: The Lounge[^]
First this makes me think of The First Law Of Optimization: Don't do it!
And then The Second Law of Optimzation: If you have to do it, don't do it yet!
This obvuiouly refers to peephole optimzation. Selecting an algorithm of lower complexity is a different matter. But worrying about how the switch construct is handled by the compiler falls in the peephole class.
When I programmed Pascal around 1980, the compiler knew a single way of coding CASE x OF statements: As a jump table with at most 256 entries. Or more exactly: Alternatives was limited to internal values 0..255. Fair enough for small student exercises, but for real code, it was just tooo limiting.
Then I got into CHILL with its decision table entries ("CASE A, B, C OF ...", with all combinations of A, B, C values, with "don't care" and ELSE and the whole works - but still static). Later comes C# with much greater flexibility. Bottom line: Tiny jump tables is a very special case. You may hope for the compiler to optimize for that particular one, but I wouldn't spend too much energy on it. In the world of modern code, it is just too special.
Then there is another thing, now that you refer to state machines: I don't believe that switch statements is a good way to implemnent state machines. Maintenance is resource demanding when you expand it with new states and events. Giving proper handling to illegal events is difficult. And any reasonably complete state machine, e.g. for a communication protocol, will have a rather sparse state table.
If you implement a sparse 2D transition table by a jump table for one dimension, each leading to a jump table in the other dimension, you implemenent that full, sparse table in a rather un-maintainable way. I would rather pack the table, and address it as a single table. So you would maintain the table in an unpacked form, and use a small compaction routine to build the runtime table when you change it.
I let the compaction routine generate the table access function as well, so that a simple table not requiring e.g. predicate handling for alternate actions will not have this access code generated.
I guess my code is not super-optimized to those tiny demo-examples to teach students the basic idea of an FSM. But if you really need the functionality of a full blown solution, then I can handle it with sufficient speed that the table lookup is certainly not a bottleneck.
State tables are tables, not "cases". Treat them as such!
|
|
|
|
|
F-ES Sitecore wrote in the Lounge: CBA doing any research, but I don't think .net actually supports the switch statement, it is just syntactic sugar, your switch statement is converted to an "if\else" block by the compiler. Is there any decent compiler around that treats all different variations on switch (/CASE) in exactly the same manner?
Even 40 years ago, when I learned CHILL - from the guy developing the CHILL compiler - did we learn about how the compiler considered various code generating alternatives, from simple jump tables up to if/else sequences as a last resort. The choice was significantly affected by the compiler options selected, whether to optimize for small code space, small data space, fastest execution etc.
This was done 40 years ago. I am sure that compiler developers have not abandoned such options.
|
|
|
|
|
Using my own two eyes, and my personal experience, I have never seen it as anything but an if\else statement. I appreciate there probably are variances, maybe ones I didn't realise were originally switch statements, but from what I've seen the .net compiler seems to heavily favour the if\else.
This convo is a lot like people arguing that god exists....they swear it does, but all I'm asking is for actual simple proof
|
|
|
|
|
Please help me out am new to see c#
How can I resolve this problem – I use OleDbDataReader to Read the Price from Database to the TextBox “Unit Price” with the currency format but the issues is the Subtotal column calculation Stop working.
See below image 1 for details. As you can see when I read the Price to the Unit Price TextBox as currency format the Subtotal stop working and the total Qty. see the code where I use the currency format.
while (reader.Read())
{
txtPrice.Text = Convert.ToDouble(reader["Price"]).ToString("C",info);
}
<pre>
But if I remove the currency format and use custom format for the textbox "Unit Price" everything work fine but I really want the currency format on the unit Price txtBox.
See when the format is removed and the custom format is used see code below and image 2.
<pre>
while (reader.Read())
{
txtPrice.Text = Convert.ToDouble(reader["Price"]).ToString("#,00.00");
SUBTOTAL CALCULATION CODE
private void Subtolcalculation()
{
for (int i = 0; i < dataGVfrontsale.Rows.Count - 1; i++)
{
CultureInfo info;
info = new CultureInfo("en-NG");
double colPrice = double.Parse(dataGVfrontsale.Rows[i].Cells[4].Value.ToString());
double colQty = double.Parse(dataGVfrontsale.Rows[i].Cells[5].Value.ToString());
double subtol = colPrice * colQty;
dataGVfrontsale.Rows[i].Cells[7].Value = subtol;
}
CODE FOR TOTAL QUANTITY / CURRENCY
private double Total1()
{
double totl = 0;
int i = 0;
for (i = 0; i < dataGVfrontsale.Rows.Count; i++)
{
totl = totl + Convert.ToDouble(dataGVfrontsale.Rows[i].Cells[5].Value);
}
return totl;
}
public void calculColumns()
{
CultureInfo info;
info = new CultureInfo("en-NG");
txtTolQty.Text = Total1().ToString("C", info);
}
<pre>
|
|
|
|
|
Of course it stops working - it fails the Parse operation because you have stuck a currency symbol in front of the number, and it doesn't know what to do with it.
Instead of working with strings all the time put the actual numeric value in the cell, and set the column style to currency - the system will do all the work for you, and there is no conversion needed once the Value is set:
myDataGridView.Columns[columnIWantAsCurrency].DefaultCellStyle.Format = "c";
"I have no idea what I did, but I'm taking full credit for it." - ThisOldTony
AntiTwitter: @DalekDave is now a follower!
modified 1-Jun-20 3:11am.
|
|
|
|
|
I am attempting to learn programming in c# to begin with and have run into an issue I can't figure out yet. Am hoping fro some help, direction, etc. The code below works just fine when I don't use any multi threading but one I try to multi thread I am getting the following error: "Argument 1: cannot convert from 'void' to 'System.Threading.ThreadStart'" This error is shown on the line "var bkpthread = new Thread(CopyDirectory(source.ToString(), target.ToString()))"
Code:
using System;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.IO;
using System.Text;
using System.Windows.Forms;
using MessageBox = System.Windows.Forms.MessageBox;
using System.Threading;
class Folders
{
#pragma warning disable IDE1006 // Naming Styles
public string pth { get; set; }
}
namespace Backup_Tool
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
foreach (var Drives in Environment.GetLogicalDrives())
{
System.IO.DriveInfo DriveInf = new System.IO.DriveInfo(Drives);
if (DriveInf.IsReady == true)
{
ddlDrives.Items.Add(DriveInf.Name);
}
}
ListView1.Items.Add(new Folders() { pth = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory) });
ListView1.Items.Add(new Folders() { pth = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) });
ListView1.Items.Add(new Folders() { pth = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile) + "\\" + "Downloads" });
ListView1.Items.Add(new Folders() { pth = Environment.GetFolderPath(Environment.SpecialFolder.MyMusic) });
ListView1.Items.Add(new Folders() { pth = Environment.GetFolderPath(Environment.SpecialFolder.MyPictures) });
ListView1.Items.Add(new Folders() { pth = Environment.GetFolderPath(Environment.SpecialFolder.MyVideos) });
}
public void ChkDest()
{
string message = "You must first select a destination";
string title = "Destination Error";
MessageBoxButtons buttons = MessageBoxButtons.OK;
MessageBox.Show(message, title, buttons, MessageBoxIcon.Warning);
}
private void Cls_Click(object sender, RoutedEventArgs e)
{
System.Windows.Application.Current.Shutdown();
}
private void AddFolder_Click(object sender, RoutedEventArgs e)
{
var fbd = new FolderBrowserDialog { };
if (fbd.ShowDialog().ToString().Equals("OK"))
ListView1.Items.Add(new Folders() { pth = fbd.SelectedPath });
}
private void FullSystem_Click(object sender, RoutedEventArgs e)
{
ChkDest();
}
private void DelFolder_Click(object sender, RoutedEventArgs e)
{
ListView1.Items.RemoveAt(ListView1.SelectedIndex);
}
private void FldBackup_Click(object sender, RoutedEventArgs e)
{
if (ddlDrives.SelectedIndex > -1 && ddlDrives.SelectedItem != null && !string.IsNullOrEmpty(ddlDrives.SelectedItem.ToString()))
{
foreach (Folders item in ListView1.Items.Cast<folders>())
{
DirectoryInfo source = new DirectoryInfo(item.pth);
string fldname = new DirectoryInfo(item.pth).Name;
DirectoryInfo target = new DirectoryInfo(ddlDrives.SelectedItem + "DataHistory\\" + fldname + "\\");
var bkpthread = new Thread(CopyDirectory(source.ToString(), target.ToString()))
{
IsBackground = true
};
bkpthread.Start();
}
}
else
{
ChkDest();
}
}
private void ComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (ddlDrives.SelectedItem.ToString().Contains("C"))
{
FlashTB.Visibility = Visibility.Visible;
tblk1.Visibility = Visibility.Visible;
}
else
{
FlashTB.Visibility = Visibility.Hidden;
tblk1.Visibility = Visibility.Hidden;
}
}
public void CopyDirectory(string SourceDirectory, string TargetDirectory)
{
string ErrorLog = "c:\\temp\\log.txt";
DirectoryInfo source = new DirectoryInfo(SourceDirectory);
DirectoryInfo target = new DirectoryInfo(TargetDirectory);
try
{
if (!source.Exists)
return;
if (!target.Exists)
Directory.CreateDirectory(target.FullName);
}
catch (IOException errorCreate)
{
using (StreamWriter writer = new StreamWriter(ErrorLog))
{
writer.WriteLine(errorCreate.Message);
}
}
try
{
FileInfo[] sourceFiles = source.GetFiles();
for (int i = 0; i < sourceFiles.Length; ++i)
File.Copy(sourceFiles[i].FullName, target.FullName + "\\" + sourceFiles[i].Name, true);
}
catch (IOException copyError)
{
using (StreamWriter writer = new StreamWriter(ErrorLog))
{
writer.WriteLine(copyError.Message);
}
}
try
{
DirectoryInfo[] sourceDirectories = source.GetDirectories();
for (int j = 0; j < sourceDirectories.Length; ++j)
CopyDirectory(sourceDirectories[j].FullName, target.FullName + "\\" + sourceDirectories[j].Name);
}
catch (IOException errorDir)
{
using (StreamWriter writer = new StreamWriter(ErrorLog))
{
writer.WriteLine(errorDir.Message);
}
}
}
}
}
|
|
|
|
|
The function that you give in the Thread constructor takes parameters, therefore ThreadStart is wanting those parameters. Looking at the documentation (HINT HINT HINT), you will see two variants of Thread: one with parameters in the target function and one without parameters. You want parameters, but the documentation says you can only pass ONE parameter. You will need a version of your CopyDirectory that takes one object containing your two parameters -- a class or struct. Something like this (my C# syntax may be off slightly since I'm not compiling this):
class CopyParameters
{
public string source;
public string target;
}
public void CopyDirectoryThreaded (Object obj)
{
string source = ((CopyParameters) obj).source;
string target = ((CopyParameters) obj).target;
CopyDirectory (source, target);
}
and then your calling code looks like
CopyParameters params = new CopyParameters ();
params.source = source.ToString ();
params.target = target.ToString ();
var bkpthread = new Thread(CopyDirectoryThreaded)
{
IsBackground = true
};
bkpthread.Start(params);
Note that you have no way of detecting when your threaded copy is done, nor any protection to prevent two threads from messing with the same directories. You should have both.
Be wary of strong drink. It can make you shoot at tax collectors - and miss.
Lazarus Long, "Time Enough For Love" by Robert A. Heinlein
|
|
|
|
|
Use a delegate in the constructor
var bkpthread = new Thread(delegate() { CopyDirectory(source.ToString(), target.ToString()); })
{
IsBackground = true
};
|
|
|
|
|
Perfect. Thank you so much.
|
|
|
|
|
In my SQL database I have 4 tables with the exact same structure. I want to query them using a generic method.. I've trieed multiple approaches, but I can'te get it right. Here's what I have so far:
private string GetVendorInitials(string tableName, int jobId)
{
using (var db = GetDataContext())
{
var result = string.Empty;
var vendorNames = (from jhv in db.GetTable()
join c in db.Companies on jhv.VendorId equals c.Id
where jhv.JobId == jobId
select c.CompanyName).ToList();
foreach (var vendorName in vendorNames)
{
var vendorInits = new string(vendorName.Split(' ').Select(x => x[0]).ToArray());
result = result + vendorInits + ",";
}
result = result.Trim();
result = result.Substring(0, result.Length - 1);
return result;
}
}
Anyone know how to do this?
Thanks
If it's not broken, fix it until it is.
Everything makes sense in someone's mind.
Ya can't fix stupid.
|
|
|
|
|
Can you pass the entity type instead of the table name?
You'll also need to have the common entities implement an interface.
public interface IVendorJob
{
int VendorId { get; }
int JobId { get; }
}
...
private string GetVendorInitials<TEntity>(int jobId) where TEntity : IVendorJob
{
using (var db = GetDataContext())
{
var vendorNames = from jhv in db.Set<TEntity>()
join c in db.Companies on jhv.VendorId equals c.Id
where jhv.JobId == jobId
select c.CompanyName;
var vendorInitials = vendorNames.AsEnumerable()
.Select(n => n.Split(' ').Select(x => x[0]).ToArray())
.Select(a => new string(a));
return string.Join(",", vendorInitials);
}
}
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
Hi,
I want to read the version information of an exe on FTP. I could not find a resource anywhere. Can someone with knowledge of the subject help me?
|
|
|
|
|
I think you would most likely need to download the file first.
|
|
|
|
|
Thank you for the answer. But I will use the file I want to check as an update file. The file size is up to 150-200Mb. At every update check, downloading the file over and over again poses a problem.
|
|
|
|
|
Then you need to find some other way. FTP allows only certain commands from the remote caller.
|
|
|
|
|
Put the version number in a text file in the same FTP directory, and update it every time you update the exe file.
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
FTP is a file transfer protocol: it doesn't care about the content of the files it transfers other than to ensure that the copy is binary identical to the original.
It contains no commands to read a version number from an EXE file as it doesn't know that any file contains a version number, much less where it is.
if you must use FTP, then I'd suggest adding a separate versioning file which contains the version of all files in the folder: download that and you can decide what does and doesn't need updates.
Personally I wouldn't use FTP for updating - you generally need a "more intelligent" solution, although that may use FTP as a transport mechanism. Most update checks are performed by the app checking back to "the mothership", not the other way around - so it already knows what version it is, and communicates that to the remote server for checking.
"I have no idea what I did, but I'm taking full credit for it." - ThisOldTony
AntiTwitter: @DalekDave is now a follower!
|
|
|
|
|
Thank you for your answer. What kind of update system can I use besides FTP? Is there anything you can offer me?
|
|
|
|
|
|
he application that I'm creating has a menu comprised of labels/headers. When you click on a menu item (a xaml Label) a drop down appears with subheaders related to that item. However, I need to make this menu customizable via XML. The idea is this, the XML outlines the header names as well as the subheader names for each menu item.
<MenuHeaders>
<Header Value="Something">
<NestedHeader1>NestedHeader1</NestedHeader1>
<NestedHeader2>NestedHeader2</NestedHeader2>
</Header>
<Header Value="Something Else">
<NestedHeader1>NestedHeader1</NestedHeader1>
<NestedHeader2>NestedHeader2</NestedHeader2>
</Header>
</MenuHeaders>
I am able to read the XML using XDocument and bind a Dependency Property to the label context. The problem is that I do not know how many menu items might be in the XML file. I wanted to avoid creating a ton of labels and dependency properties for the label content to bind to. Instead of creating labels in xaml and binding to a property in C#, can I create UI items in C# and populate them with elements from a list at run time? There's some code below of how I'm getting and binding the data to a preexisting label.
C#:
<pre>
public string HeaderName
{
get => (string)GetValue(HeaderNameProperty);
set => SetValue(HeaderNameProperty, value);
}
public static readonly DependencyProperty HeaderNameProperty =
DependencyProperty.Register("HeaderName", typeof(string), typeof(MainWindow));
private void LoadHeaders()
{
var msg = new List<string>(0);
XDocument doc = null;
try
{
doc = XDocument.Load("MenuHeaders.xml");
}
catch (Exception e)
{
msg.Add(string.Format("Unable to open file:{0}", ""));
msg.Add(e.Message);
}
if(doc != null)
{
var allHeaders = doc.Descendants("Header").ToList();
List<string> headers = new List<string>();
foreach(XNode node in allHeaders)
{
XElement element = node as XElement;
foreach(XAttribute attribute in element.Attributes())
{
headers.Add(attribute.Value);
}
}
HeaderName = headers[0];
}
}
XAML:
<stackpanel x:name="Stack">
(As you may have noticed, I'm only adding the Header attributes to the List and none of the subheaders. This code is not complete but it's what I currently have) I will appreciate any help.
|
|
|
|
|
You need to put a secondary loop into the Header loop to get the children of the header.
How do you intend to bind the actions to the menu item?
Never underestimate the power of human stupidity -
RAH
I'm old. I know stuff - JSOP
|
|
|
|
|
The XMLDataProvider might be a simpler option:
How to: Bind to XML Data Using an XMLDataProvider and XPath Queries - WPF | Microsoft Docs[^]
If you want to stick with code, you're going to need a class to represent the menu item. For example:
public class MenuHeaderItem
{
public string HeaderName { get; set; }
public IReadOnlyList<MenuHeaderItem> Children { get; set; }
}
public static IReadOnlyList<MenuHeaderItem> LoadMenu(XDocument document)
{
var result = new List<MenuHeaderItem>();
var allHeaders = document.Descendants("Header");
foreach (XElement node in allHeaders)
{
result.Add(new MenuHeaderItem
{
HeaderName = (string)node.Attribute("Value"),
Children = node.Elements().Select(el => new MenuHeaderItem
{
HeaderName = (string)el,
}).ToList(),
});
}
return result;
} Bind the loaded values to a read-only dependency property:
private static readonly DependencyPropertyKey MenuHeadersKey = DependencyProperty.RegisterReadOnly(
"MenuHeaders",
typeof(IReadOnlyList<MenuHeaderItem>),
typeof(YourContainingClass),
new PropertyMetadata(null)
);
public static readonly DependencyProperty MenuHeadersProperty = MenuHeadersKey.DependencyProperty;
public IReadOnlyList<MenuHeaderItem> MenuHeaders
{
get { return (IReadOnlyList<MenuHeaderItem>)GetValue(MenuHeadersProperty); }
private set { SetValue(MenuHeadersKey, value); }
}
private void LoadHeaders()
{
if (File.Exists("MenuHeaders.xml"))
{
XDocument document = XDocument.Load("MenuHeaders.xml");
MenuHeaders = LoadMenu(document);
}
} Then bind the MenuHeaders collection to your menu.
<Menu ItemsSource="{Binding Path=MenuHeaders}">
<Menu.ItemContainerStyle>
<Style TargetType="{x:Type MenuItem}">
<Setter Property="Header" Value="{Binding Path=HeaderName}" />
<Setter Property="ItemsSource" Value="{Binding Path=Children}" />
<Setter Property="Command" Value="{Binding Path=MenuClickCommand}" />
<Setter Property="CommandParameter" Value="{Binding Path=HeaderName}" />
</Style>
</Menu.ItemContainerStyle>
</Menu> (I've assumed that you have an ICommand instance on your view-model called MenuClickCommand which will receive the header name as its parameter and handle the menu click event.)
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
I am creating an application using c# winform to create and mount ISO files like wincdemu. I am able to create the ISO file and mount it like a local drive. I want to mount the image with disc type CD-ROM/DVD-ROM. I am using AttachVirtualDisk() to mount the image.
Is there any API/library support to mount the image with disc type CD-ROM/CD-R/CD-RW/DVD-ROM/DVD-RAM etc. ?
I appreciate any advice.
|
|
|
|
|