While writing a plugin for Autocad (drawing software) i create a 3d point build upout of 3 double values representing the X, the Y and the Z value for a point in 3d.
Point3d insertPoint = new Point3d((insPointX = StrToDouble(tbInsPointX.Text)),
insPointY = StrToDouble(tbInsPointY.Text),
insPointZ = StrToDouble(tbInsPointZ.Text));
and the StrToDouble looks like this:
public double StrToDouble(string str)
{
double x = 0;
try
{
x = double.Parse(str.Replace(",", "."));
}
catch (System.Exception ex) { MessageBox.Show(ex.Message); }
return x;
}
But now its actually always returning an double, as when the parse fails it returns the double as 0.
I am wondering now what would be the right way to report back to the 3dpoint creation that there was an error and it should no longer continue.
I can think of using a bool or something, but i think it might not be a nice clean way to do this. As im only a hobby programmer im not sure what the right way is to do this.
Letting it stop when the double = 0 is not an option as it can actually be a real value.
You're probably looking for double.TryParse, which has the added advantage that it doesn't throw exceptions.
double output;
if (double.TryParse(input, out output))
{
// Success
}
else
{
// Failure
}
Pretty much all 'struct' types in .NET (numbers, DateTime, TimeSpan, etc) have a TryParse method, if you're every looking for similar functionality.
To answer your follow up, you could wrap the parsing of a Point3d into a similar TryParse method:
private static bool TryParsePoint3d(string x, string y, string z, out Point3d output)
{
double xValue, yValue, zValue;
if (double.TryParse(x, out xValue) &&
double.TryParse(y, out yValue) &&
double.TryParse(z, out zValue))
{
output = new Point3d(xValue, yValue, zValue);
return true;
}
// out params must be assigned, use null if it's a class
output = new Point3d();
return false;
}
Which you can use as
Point3d insertPoint;
if (TryParsePoint3d(tbInsPointX.Text, tbInsPointY.Text, tbInsPointZ.Text,
out insertPoint))
{
insertPoint is safe to use
}
Related
I'm working on an importer for LitJson, to import float values from ints, and doubles, and if overflow-checking is enabled, I want to wrap a potential overflow exception in a JsonException with a bit more information about the failure.
Right now my code looks like this, and I don't know if I need to/can check if the context is checked or not:
private static float DoubleFloatImporter(double value) {
try
{
return (float)value;
}
catch (Exception ex)
{
throw new JsonException("Value is not a valid Single", ex);
}
}
You may be thinking of checked and unchecked contexts, but these are not relevant for your example, the explicit conversion (cast) from double to float (so from double-precision binary floating point to single-precision).
A finite double value may round to an infinite float value (either float.PositiveInfinity or float.NegativeInfinity).
For example DoubleFloatImporter(1.23e123). As a double, the input 1.23e123 will be represented as a finite value, but when cast to float, the nearest representable value will be interpreted as +∞.
Edit: As I say in comments, something like:
private static float DoubleFloatImporter(double value) {
var converted = (float)value;
if (!float.IsFinite(converted))
throw new JsonException("Converted value would become infinite or not a number");
return converted;
}
may suit your need.
What about something like this:
static float DoubleFloatImporter(double value)
{
if (double.IsPositiveInfinity(value))
{
return float.PositiveInfinity;
}
if (double.IsNegativeInfinity(value))
{
return float.NegativeInfinity;
}
if (value > Single.MaxValue || value < Single.MinValue)
{
throw new OverflowException($"'{value}' doesn't fit");
}
return (float)value; //Single.CreateChecked(value);
}
Some examples:
using System.Runtime.CompilerServices;
Convert(1.0);
Convert(double.MaxValue);
Convert(double.PositiveInfinity);
Convert(double.NegativeInfinity);
Convert((double)float.MaxValue + 100);
Convert((double)float.MaxValue * 2);
Convert(double.NaN);
static void Convert(double v, [CallerArgumentExpression("v")] string arg1Exp = "?")
{
try
{
var f = DoubleFloatImporter(v);
Console.WriteLine($"{arg1Exp} -> {f}");
}
catch (Exception ex)
{
Console.WriteLine($"{arg1Exp} -> {ex.Message}");
}
}
The output:
1.0 -> 1
double.MaxValue -> '1.7976931348623157E+308' doesn't fit
double.PositiveInfinity -> ∞
double.NegativeInfinity -> -∞
(double)float.MaxValue + 100 -> 3.4028235E+38
(double)float.MaxValue * 2 -> '6.805646932770577E+38' doesn't fit
double.NaN -> NaN
I wrote this function:
public static float parseFloat(string number)
{
float ishod = 0;
try
{
float.TryParse(number.Replace(".", ","), out ishod);
}
catch(Exception ex)
{
ishod = -1;
Console.WriteLine("parseFloat(): " + ex.Message);
}
return ishod;
}
because when entering float numbers like 4.5 in console application, it doesn't see the dot so it glues the two numbers. I get 45.
Though it will work, it is dubious when you pass 0 or -1 since you don't know if it produces error or a proper result.
I was wondering, does float type in C# has some number constant that represents an error state, so that I can return it and be sure something failed?
On the other hand what would be an error constant for integer in C#?
Or I should rethink my function and make it differently?
Well, floating point values have two kind of separators: decimal and thousand, e.g.
123,456,789.12
When parsing, thousand separators are ignored while decimal is turned into decimal point: "123,456,789.12" -> 123456789.12.
Please, note, that both separators are culture specific:
"123.456.789,12" // Russian Culture, "ru-RU" - comma is a decimal separator
"123,456,789.12" // English Culture "en-US" - dot is a decimal separator
In your case, you want to treat '.' as a decimal separtor, that's why let's parse it with Invariant Culture (your current culture treats '.' as a thousand separator and ignores it: "1.2" -> 12):
using System.Globalization;
...
public static float parseFloat(string number) {
// float.TryParse doesn't throw exceptions but returns true or false
if (float.TryParse(number,
NumberStyles.Any,
CultureInfo.InvariantCulture,
out float result))
return result;
else {
Console.WriteLine("Invalid floating point value.");
// Not A Number
return float.NaN;
}
}
Possible usage:
float value;
do {
Console.Write("Enter the value, please: ");
// Keep asking user
value = parseFloat(Console.ReadLine());
}
while (float.IsNaN(value)); // while the input provided is invalid
The TryParse method will not throw an exception in case of failure, it will simply return false. This makes your method redundant - you can simply do:
if(float.TryParse(someStringValue, out float ishod))
{
// success
}
else
{
Console.WriteLine("failed to parse {0} to float.", someStringValue);
}
If you really want to return a float whatever the conversion makes then you can return NaN when you are sure:
public static float parseFloat(string number)
{
float ishod = 0;
try
{
float.TryParse(number.Replace(".", ","), out ishod);
}
catch(Exception ex)
{
ishod = float.NaN;
Console.WriteLine("parseFloat(): " + ex.Message);
}
return ishod;
}
I created a validation function as below:
public static T getAsDigit<T>( this Textbox tb, float min, float max ){
}
Most of the time, the validation range is specificed in integers. It works fine. But when I try to pass in decimals, it give me error sth like can't convert double to float, I have to change defination to double.
I am new to C#, how can I pass in the digits as float ? without doing sth unintuitive like Convert.toFloat('1.3').
My use case only requires 3 decimal place precision, value range 0.000 ~ 10.000. Is there any disadvantage in using float versus double in C#? Since I used and saw people use float a lot in sql when decimal() is optional.
Use f literal: getAsDigit(1.34f)
Or cast value to float getAsDigit((float)1.34)
You have to convert the double to flow so i recommend you do
float.Parse(x)
the cleaner option would be to create a new var and convert it to float there instead of in the injection so something like this:
double x = 1.3;
var newFloat = float.Parse(x);
I think you want to write a validation for the value of the TextBox.
You can upgrade your method to make it generic for all value type struct
public static T getAsDigit<T>(this TextBox tb, T min, T max) where T : struct, IComparable<T>
{
var valueConverted = default(T);
try
{
valueConverted = (T)Convert.ChangeType(tb.Text, typeof(T));
}
catch(Exception e)
{
//do something you want, rethown i.e
}
if (valueConverted.CompareTo(max) > 0)
return max;
if (valueConverted.CompareTo(min) < 0)
return min;
return valueConverted;
}
And you can simply pass the type you want.
string a = "10.5"; // suppose that a is TextBox.Text
var b = a.getAsDigit<float>(10,11); // return 10.5f
var c = a.getAsDigit<decimal>(11,12); //return 11d
var d = a.getAsDigit<double>(9,10); //return 10d
Assume we have a huge list of numeric cartesian coordinates (5;3)(1;-9) etc. To represent a point in oop I created a struct/object (c#):
public struct Point
{
public int X, Y { get; }
public Point(int x, int y)
{
// Check if x,y falls within certain boundaries (ex. -1000, 1000)
}
}
It might be wrong of how I am using struct. I guess normally you would not use a constructor but this is not the point.
Suppose I want to add a list of 1000 points and there is no guarantee that these coordinates fall within boundaries. Simply if the point is not valid, move to the next one without failing and inform user about it. As for object, I would think that Point should be responsible for instantiation and validation by itself but I am not sure how to deal with it in this particular case. Checking x, y beforehand by the caller would be the simplest approach but it does not feel right because caller would have to handle logic that should reside in Point.
What would the most appropriate approach to validate and handle incorrect coordinates without failing and violating SRP?
You can't do this in the constructor; the constructor either runs succesfully or it doesn't. If it doesn't its because an exception is raised, so, so much for silently failing. You could catch exceptions but that woul basically mean you are using exceptions as a control flow mechanism and that is a big no no, don't do that!
One solution similar to what you are thinking is to use a static factory method:
public struct Point
{
public static bool TryCreatePoint(int x, int y, Bounds bounds, out Point point)
{
if (x and y are inside bounds)
{
point = new Point(x, y);
return true;
}
point = default(Point);
return false;
}
//...
}
And the code adding points to the list should act based upon creation success.
Fun fact: if you are using C# 7 the code could look a lot cleaner:
public static (bool Succesful, Point NewPoint) TryCreatePoint(int x, int y, Bounds bounds)
{
if (x and y are inside bounds)
return (true, new Point(x, y));
return (false, default(Point));
}
I can think of three options:
Have the constructor throw an exception that you catch. This is not really great if you are expecting a lot of failures.
Have an IsValid property on the struct that you can use to filter it out once created.
Have the thing loading the data take responsibility for validating the data as well. This would be my preferred option. You say "it does not feel right because caller would have to handle logic that should reside in Point" but I would argue that the responsibility for checking that loaded data is correct is with the thing loading the data, not the data type. You could also have it throw an ArgumentOutOfRangeException in the constructor if the inputs are not valid now that you are no longer expecting anything invalid to be passed as a belt and bracers approach to things.
What you want to do is simply not posible, an instance of a class is either fully created or not at all. If the constructor has been called the only way to not instantiate an instance is by throwing an exception.
So you have these two opportunities to do this:
Extract a method Validate that returns a bool and can be called from the caller of your class.
public struct Point
{
public int X, Y { get; }
public Point(int x, int y)
{
}
}
public bool Validate() { return -1000 <= X && X <= 1000 && -1000 <= Y and Y <= 1000; }
Of course you could do the same using a property.
Throw an exception in the constructor
public Point(int x, int y)
{
if(x > 1000) throw new ArgumentException("Value must be smaller 1000");
// ...
}
However the best solution IMHO is to validate the input before you even think about creating a point, that is check the arguments passed to the constructor beforehand:
if(...)
p = new Point(x, y);
else
...
To be honest, Point shouldn't check boundaries, so the caller should do that. A point is valid in the range that their X and Y can operate (int.MinValue and int.MaxValue). So a -1000000,2000000 is a valid point. The problem is that this point isn't valid for YOUR application, so YOUR application (the caller), the one who is using point, should have that logic, not inside the point constructor.
Structs in C# are funny so I'll add another "funny" way to check:
struct Point
{
int _x;
public int X
{
get { return _x; }
set { _x = value; ForceValidate(); }
} // simple getter & setter for X
int _y;
public int Y
{
get { return _y; }
set { _y = value; ForceValidate(); }
} // simple getter & setter for Y
void ForceValidate()
{
const MAX = 1000;
const MIN = -1000;
if(this.X >= MIN && this.X <= MAX && this.Y >= MIN && this.Y <= MAX)
{
return;
}
this = default(Point); // Yes you can reasign "this" in structs using C#
}
}
I am in need of some help here about doing a dynamic instantiation in C#. What I want to accomplish is to be able to use a string variable that is used as the name in the instantiation. I think you can use reflection or something, but I am lost on this one. Here is my test code snippet and hopefully someone has an answer.
Averages is tied to a class that handles everything. So lets say I wanted to make test the variable and everything that is tied to the string of test could be passed as the instantiation. How could I create an object that can handle the variable test coming in, compile and be used in runtime? I know this may sound out of the ordinary, but instead of me using many IF's with multiple declarations of doubles. I could use a dynamic instantiation. Anyone that can help out I would be most appreciative.
Averages test = new Averages();
double[] testresult;
testresult = test.sma();
womp,,,I want to dynamically declare arrays of doubles. I already know how to declare a static array. What I am trying to accomplish is eliminating declaring 30 arrays that bascially do the same thing over and over again with a different naming.
So instead of doing this:
if (UITAName == "SMA")
{
Averages sma = new Averages();
double[] smaresult;
smaresult = sma.sma(UITAName, YVal, UITPeriod, UITShift);
chart1.Series[UITA].Points.DataBindXY(test2, test1);
}
if (UITAName == "TMA")
{
Averages tma = new Averages();
double[] tmaresult;
tmaresult = tma.tma(UITAName, YVal, UITPeriod);
chart1.Series[UITA].Points.DataBindXY(XVal, tmaresult);
}
else
if (UITAName == "EMA")
{
Averages ema = new Averages();
double[] emaresult;
emaresult = ema.ema(UITAName, YVal, UITPeriod);
chart1.Series[UITA].Points.DataBindXY(XVal, emaresult);
}
I want to do this only once for everything instead of doing IF statements. The problem is that you cannot compile with a declaration of a string. There has to be a way I just do not know how.
Averages UITAName = new Averages();
double[] UITANameresult;
UITANameresult = UITAName.UITAName(UITAName, YVal, UITPeriod);
chart1.Series[UITA].Points.DataBindXY(XVal, UITANameresult);
You can instantiate a class dynamically using Reflection, with Activator.CreateInstance.
Activator.CreateInstance("MyAssembly", "MyType");
However I'm not entirely clear on what you're trying to do. If you already have a class called Averages, what do you need dynamically instantiated? And I'm a bit worried by what you mean that it's "tied to a class that handles everything"...
Sounds like you might need to check out Func<> ??? Just my initial assessment without seeing a little more code to give me a clearer context.
To clarify, if you are wanting to pass the values as an argument, like you would on your command line, then you would need to instance the assembly. Otherwise, with Func<T, TResult> you can pass parameters dynamically to a method and get the return value.
Okay...if I get what you are saying...you want something that would resemble:
class Average
{
public double[] sma()
{
// do something
return dArray;
}
public double[] ema()
{
// do something
return dArray;
}
}
that is...the function 'name' would be the value of the string returned from a database query of some sort?
...and if that is the case then I don't know why you wouldn't just do a dictionary like:
Dictionary<string, double[]> testResults = new Dictionary<string, double[]>();
void GetDoubles(string name, params double[] args)
{
testResult[s] = GetAverages(args);
}
I think this could help you.
If i understand you correctly, you have method initinialization values in db as SMA,EMA,etc and you need to invoke the method at runtime,
string invokeMethod = GetValueFromDB() //ur logic to get the SMA or EMA or TMA from db
Type urType=typeof("yourclassname");
object unKnownObj = Activator.CreateInstance(urType);
//Fill your paramters to ur method(SMA,EMA) here
//ie, sma.sma(UITAName, YVal, UITPeriod, UITShift);
object[] paramValue = new object[4];
paramValue[0] = UITAName;
paramValue[1] = YVal;
paramValue[2] = UITPeriod;
paramValue[3] = UITShift;
object result=null;
try
{
result = urType.InvokeMember(invokeMethod, System.Reflection.BindingFlags.InvokeMethod, null, unKnownObj, paramValue);
}
catch (Exception ex)
{
//Ex handler
}
So this way you can avoid the multiple if loops and will invoke the method directly by the given name..
I think reflection might not be the best solution for your situation. Maybe decomposing your code a little bit might help, something along the following lines...
public interface ICalculation
{
double [] Calculate(double y, double period, double shift);
double XVal {get;}
}
public class SMA : ICalculation
{
public override double[] Calculate( double y, double period, double shift )
{
// do calculation, setting xval along the way
}
// more code
}
public class EMA : ICalculation
{
public override double[] Calculate( double y, double period, double shift )
{
// do calculation, setting xval along the way
}
// more code
}
public class Averages
{
public void HandleCalculation( ICalculation calc, double y, double p, double s )
{
double[] result = calc.Calculate( y, p, s );
chart.Series[UITA].Points.DataBindXY( calc.XVal, result );
}
}