I've been tasked with converting some legacy code to a new system and we've got some VB6 structures that are here. Is there a way to convert them into a C# structure easily?
I could redefine the structure in C# but there's no fixed strings in C#. (Or maybe I misunderstand)
Any prods in the right direction?
Private Type MapRec
Name As String * NAME_LENGTH
Revision As Long
Moral As Byte
Up As Integer
Down As Integer
Left As Integer
Right As Integer
Music As String
BootMap As Integer
BootX As Byte
BootY As Byte
Tile() As TileRec
Npc(1 To MAX_MAP_NPCS) As Integer
NpcSpawn(1 To MAX_MAP_NPCS) As SpawnRec
TileSet As Integer
Region As Byte
End Type
With respect to fixed-length strings, yikes. It ain't gonna happen because there is no equivalent construct. Unless Jon Skeet or Anders Hejlsberg know differently and can be invoked to weigh in -- I don't think even they know a way, cuz there ain't one, I am pretty certain.
On the other hand, fixed-length strings are absolutely Satanic. Which is why they didn't include them in .NET. :-)
If you were to ask me how I would convert the above MapRec object to something usable in C#, well you kind of have your choice between a struct and a class. Personally, I dislike structs. If you used a class, then you could implement a kind of bastardized fixed-string by way of your setters and getters. As seen in this example, which is how I would implement your Type MapRec:
public class MapRec
{
private const int MAX_MAP_NPCS = 25;
private int fixedLength1 = 10;
private string _name;
public string Name
{
get
{
return _name;
}
set
{
if (value.Length != fixedLength1)
{
if (value.Length < fixedLength1)
{
_name = value.PadRight(fixedLength1);
}
else
{
_name = value.Substring(0,fixedLength1);
// or alternatively throw an exception if
// a 11+ length string comes in
}
}
else
{
_name = value;
}
}
}
// Constructor
public MapRec()
{
Npc = new int[MAX_MAP_NPCS];
NpcSpawn = new SpawnRec[MAX_MAP_NPCS];
}
public long Revision { get; set; }
public byte Moral { get; set; }
public int Up { get; set; }
public int Down { get; set; }
public int Left { get; set; }
public int Right { get; set; }
public string Music { get; set; }
public int BootMap { get; set; }
public byte BootX { get; set; }
public byte BootY { get; set; }
public TileRec[] Tile { get; set; }
public int[] Npc { get; set; }
public SpawnRec[] NpcSpawn { get; set; }
public int TileSet { get; set; }
public byte Region { get; set; }
}
In the end, unless one actually needs a fixed-length string (and perhaps Microsoft.VisualBasic.VBFixedStringAttribute could do the job), I would suggest staying the heck away from them.
You may be interested in the VBFixedStringAttribute, and the VBFixedArrayAttribute although they are only utilized in a few places.
See also this question and this question.
Related
I have a simple class defined like this:
public class StickColumns
{
public string wellname { get; set; }
public double WellLength { get; set; }
}
In the code, I get some data as list<double> perfdepth; assume this is perfdepth1,perfdepth2,perfdepth3. Of course, this list is dynamic hence, I wouldnt know beforehand to change my class definition to:
public class StickColumns
{
public string wellname { get; set; }
public double WellLength { get; set; }
public double perfdepth1 { get; set; }
public double perfdepth2 { get; set; }
public double perfdepth3 { get; set; }
}
Can these new members be created during run time?
The reason why I think I would need this is because of data binding in WPF. Eventually I need to display "point series"; Perfdepth1 as one series, perfdepth2 as another series and so on, i.e, dynamic number of Perfdepths.
If there is a simpler way to do it, I am all ears!
You might just want to use the dynamic type with ExpandoObject..
dynamic stickColumns = new ExpandoObject();
stickColumns.wellName = "Something";
stickColumns.perfdepth1 = "Something Else";
It has its drawbacks as it does mean you end up with runtime errors etc... but it can be useful for this type of scenario.
I've seen a lot of different examples of how to do this and am well aware that I could write out a loop that iterates my entire tree of classes to find the maximum depth, but I cannot help but think there has to be a simpler way.
Basically I have two classes that I developed to host all my applications settings, SettingGroup which is exactly what it sounds like, basically a folder, and Setting which is the setting itself and the configurations that allow the application to know what the setting is for and how to display it. The reason I dont just use a fixed class and write out field for my settings is that the application is plugin driven and I wish the settings to remain centralized is plugins are added or removed and not have to worry about decentralized data from the plugins.
When dynamically creating the settings page it is necessary to know the maximum depth of any particular SettingGroup so I know if the root should first organized by tabs, pages, sections etc...
Long story short, is there a reasonably lightweight way to determine the groups maximum depth?
public enum DescriptionVisibility { None, SubText, ToolTip };
public enum SettingType { Bool, Integer, Decimal, Text };
public enum SettingControl { Checkbox, Textbox, Slider, Radio, Dropdown, TextField, Color};
public class SettingGroup
{
public string name { get; set; }
public string description { get; set; }
public List<SettingGroup> groups { get; set; }
public List<Setting> settings { get; set; }
}
public class Setting
{
public string name { get; set; }
public string description { get; set; }
public DescriptionVisibility descriptionVisibility { get; set; }
public Dictionary<string, dynamic> configuration { get; set; }
public dynamic settingValue { get; set; }
public SettingType settingType { get; set; }
public SettingControl settingControl { get; set; }
}
Edit: this is untested, but this is what I am currently considering using;
private static int getDepth(this SettingGroup group, int depth = 0)
{
if (group.groups == null)
return depth;
if (group.groups.Count == 0)
return depth;
int returnDepth = depth;
foreach (SettingGroup subGroup in group.groups)
{
int subGroupDepth = subGroup.getDepth(depth + 1);
if (subGroupDepth > returnDepth)
returnDepth = subGroupDepth;
}
return returnDepth;
}
Its pretty basic so it couldn't be TOO slow, but still seems bulky, is there not a LINQ way to do this perhaps?
This question already has answers here:
C# equivalent to VB6 'Type'
(4 answers)
Closed 9 years ago.
I have an old system in VB6, now I'm trying to build a new one using C#.
I have this VB6 Code:
Private Type T_Parameters
Name As String * 16 (What is this ? '* 16')
YearsOld As Byte
Day As Byte
End Type
What would be the equivalent code in C# ? What is this Type ?
It's been a long time since I've looked at VB 6 code, but I believe that's a fixed-length string. .NET doesn't support fixed-length strings, but you can come close with a char[]. I believe the C# equivalent would be:
private class T_Parameters
{
public string Name { get; set; }
public byte YearsOld { get; set; }
public byte Day { get; set; }
}
Or possibly this, which would prevent the user from changing the size of the Name field:
private class T_Parameters
{
public char[] Name { get; private set; }
public byte YearsOld { get; set; }
public byte Day { get; set; }
public T_Parameters() {
Name = new String(' ', 16).ToCharArray();
}
}
Alternatively, you could do this:
private class T_Parameters
{
private string name = new String(' ', 16);
public string Name
{
get { return this.name; }
set { this.name = value.PadRight(16, ' ').Substring(0, 16); }
}
public byte YearsOld { get; set; }
public byte Day { get; set; }
}
Make it a struct, like this:
private struct T_Parameters
{
string Name;
byte YearsOld;
byte Day;
}
Or a class, like this:
public class T_Parameters
{
public string Name { get; set; }
public byte YearsOld { get; set }
public byte Day { get; set; }
}
How to decide between class or struct?
Choose struct, if:
The object is small
The values are going to be immutable (read: not changing)
You have lots of objects
Otherwise, choose class.
Are you looking to build a struct?
private struct T_Parameters
{
string Name;
byte YearsOld;
byte Day;
}
I am working on a trading API (activex from interactive brokers)which has a method called:
void reqMktDataEx(int tickerId, IContract contract, string generalDetails, int snapshot)
The issue is around the last parameter "int snapshot" which obviously requires an int input which actually indicates that whether trader wanna snapshot market data or not. So I guess that if I set it to non-zero, then the implicit conversion would convert this non-zero to be bool value "true".
However, I am using c# to connect to this api. Everything was fine until this one. I tried this:
A. void reqMktDataEx(1, AUDUSD, "100", 0)
Please ignore the first three parameters "1, AUDUSD, "100"", the only matter is the last one 0 as int. I got paused during debugging and the information is :
"Specified cast is not valid. Invalidcastexception is unhandled" and "when casting from a number, the number must not be infinity".
After this I learned that here is a difficulty for c# to treat 1 as bool true and 0 as bool false IMPLICITLY according this
web http://www.dotnetperls.com/convert-bool-int
B. I tried this
void reqMktDataEx(1, AUDUSD, "100", Convert.ToInt16(false)) I got similar error again.
C. I tried again this one:
void reqMktDataEx(1, AUDUSD, "100", int.Parse("false"))
the complaint is input string was not in a correct format. Make sure that you method arguments are in the right format.
MY GUESS:
Here is a inside configuration of C# which does not treat 0 as false and 1 as true. Is there any way to solve?
First Edit
As suspected by one professional programmer below, I post the contract class and audusd definition here for him.
namespace InteractiveBrokersTradingSystem
{
class Contract:TWSLib.IContract
{
public int conId { get; set; }
public string symbol { get; set; }
public string secType { get; set; }
public string expiry { get; set; }
public double strike { get; set; }
public string right { get; set; }
public string multiplier { get; set; }
public string exchange { get; set; }
public string primaryExchange { get; set; }
public string currency { get; set; }
public string localSymbol { get; set; }
public int includeExpired { get; set; }
public object comboLegs { get; set; }
public object underComp { get; set; }
public string comboLegsDescrip { get; set; }
public string secIdType { get; set; }
public string secId { get; set; }
}
}
namespace InteractiveBrokersTradingSystem
{
class Forex:Contract
{
public Forex(string preCurrency,string baseCurrency)
{
//conId = 14433401;
symbol = preCurrency;
secType = "CASH";
exchange = "IDEALPRO";
currency = baseCurrency;
strike = 0;
includeExpired = 0;
primaryExchange = "IDEALPRO";
}
}
}
The method I use to call the reqMktDataEx:
implementation first, simple inheritance:
public void MyReqMarketData(int tickId, IContract contract, string tickTypes, int snapshot)
{
reqMktDataEx(tickId, contract, tickTypes, snapshot);
}
private void AudButtonItemItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
{
Forex audusd = new Forex("AUD", "USD");
_myTwsClass.MyReqMarketData(1,audusd, "100", 0);
}
Second Edit:
System.InvalidCastException was unhandled
Message=Unable to cast object of type 'InteractiveBrokersTradingSystem.Forex' to type 'TWSLib.IContract'.
Source=InteractiveBrokersTradingSystem
It seems that here is some casting problem between the forex class I defined and the Icontract com thing. Here is my new definition:
namespace InteractiveBrokersTradingSystem
{
class Forex
{
public int conId { get; set; }
public string symbol { get; set; }
public string secType { get; set; }
public string expiry { get; set; }
public double strike { get; set; }
public string right { get; set; }
public string multiplier { get; set; }
public string exchange { get; set; }
public string primaryExchange { get; set; }
public string currency { get; set; }
public string localSymbol { get; set; }
public int includeExpired { get; set; }
public object comboLegs { get; set; }
public object underComp { get; set; }
public string comboLegsDescrip { get;set; }
public string secIdType { get; set; }
public string secId { get; set; }
public Forex(string preCurrency,string baseCurrency)
{
//conId = 0;
//symbol = preCurrency;
//secType = "CASH";
//expiry = null;
//strike = double.Parse("0");
//right = null;
//multiplier = null;
//exchange = "IDEALPRO";
//primaryExchange = "IDEALPRO";
//currency = baseCurrency;
//localSymbol = null;
//includeExpired = 0;
//comboLegs = null;
//underComp = null;
//comboLegsDescrip = null;
//secType = null;
//secId = null;
}
}
}
As you can see that the Forex class inherits from the TWS.IContract. how it could not be cast to Icontract successively?
There is no implicit conversion of a bool to an int. Only an explicit one:
Convert.ToInt32(someBool)
// or...
someBool ? 1 : 0
From that site you linked:
First, you cannot implicitly convert from bool to int. The C# compiler uses this rule to enforce program correctness. It is the same rule that mandates you cannot test an integer in an if statement.
Edit
int doesn't have a concept of infinity. Only float and double do. This means it won't be related to that parameter, unless that parameter just controls the flow of the code that is actually crashing. Which still means it isn't the conversion causing the problem.
You're getting a different error for int.Parse("false") because it is expecting a number, not a true/false value. This will always throw an exception at runtime, but it will throw in your code, not in the library's code.
I'm starting to think it is the second parameter, contract, for which you've supplied AUDUSD.
One more way is to have extension method:
public static class BooleanExtensions
{
public static int ToInt(this bool value)
{
return value ? 1 : 0;
}
}
then it can be used:
bool result = false;
result.ToInt();
make field tinyint in database
tinyint fieldname;
c# code
convert.toint32(fieldname.tostring());//returns 1 or 0
to get boolean value
covert.tobool(fieldname.tostring()) ;
There's no implicit cast to int from bool. So make your own. Then add them up.
Boolean
byFinancialCenter = false,
byProvider = false,
byServiceSite = false,
byProcedure = false;
int b2i(bool source) => source ? 1 : 0;
int ForeignKeyCount() => b2i(byFinancialCenter) + b2i(byProvider) + b2i(byServiceSite) + b2i(byProcedure);
The b2i is generic, as I needed the specific count in several places, including the last function makes it easy to use. Also, for maintenance, having the embedded function just under the bools makes it more likely that subsequent developers will see what's happening.
I have a number of classes that are all related conceptually, but some more-so at the details level than others. For example, these three classes have nearly identical properties (although member functions will vary):
public class RelatedA : IRelatedType
{
public string Name { get; set; }
public string Value { get; set; }
public DateTime Stamp { get; set; }
}
public class RelatedB : IRelatedType
{
public string Name { get; set; }
public string Value { get; set; }
public DateTime Stamp { get; set; }
}
public class RelatedC : IRelatedType
{
public string Name { get; set; }
public string Value { get; set; }
public DateTime Stamp { get; set; }
public int Special { get; set; }
}
There are a couple of other classes that are conceptually related to the above 3, but can be a bit different implementation-wise:
public class RelatedD : IRelatedType
{
public string Name { get; set; }
public string Statement { get; set; }
}
public class RelatedE : IRelatedType
{
public string Name { get; set; }
public string Statement { get; set; }
public bool IsNew { get; set; }
}
Instances of these can be created by a factory based on some sort of "type" enumerated value. The problem is that later on when these objects are being used (in a business layer, for example), there could be a lot of code like this:
IRelatedType theObject = TheFactory.CreateObject(SomeEnum.SomeValue);
if (theObject is RelatedC)
{
RelatedC cObject = theObject as RelatedC;
specialVal = cObject.Special;
}
else if (theObject is RelatedD)
{
RelatedD dObject = theObject as RelatedD;
statementVal = dObject.Statement;
}
else if (theObject is RelatedE)
{
RelatedE eObject = theObject as RelatedE;
statementVal = eObject.Statement;
isNewVal = eObject.IsNew;
}
This could be repeated in many places. Is there a better approach to the design that I should be using (there's got to be)?
You could try and factor the differences into seperate classes that are then provided so for example:
IRelatedType theObject = TheFactory.CreateObject(SomeEnum.SomeValue);
RelatedTypeHelper theHelper=TheFactory.CreateHelper(theObject);
theHelper.DoSpecialThing(theObject);
Now you won't have to have all the if else blocks, and if you add a new type which requires new handling, you just whip up a new helper implement the required pieces and you should be good to go. The helper should help document this process.
I would also question why a single method would have such a different implementation for specialVal and StatementVal could be your sample, but It makes me curious what your really doing here. can you simplify things back taking a step back and questioning the point of these being included in this specific hierarchy.