I am currently building a class library to handle unit measurements and I wanted to use the factory pattern with static methods to create lengths or areas and so on.
To keep the methods consistent I wanted to create an interface or a superclass. Is there a possible way to enforce subclasses to implement a static method?
(Offtopic: Is it also possible to enforce subclasses to overload operators?)
For example:
public class Length
{...
public static Length Create(double value, string unitCode)
{
var length = new Length();
switch (unitCode)
{
case "Mm":
length.Megameters = value;
break;
case "Km":
case "km":
length.Kilometers = value;
break;
case "hm":
length.Hectometers = value;
break;
case "dam":
length.Decameters = value;
break;
case "m":
length.Meters = value;
break;
case "dm":
length.Decimeters = value;
break;
case "cm":
length.Centimeters = value;
break;
case "mm":
length.Millimeters = value;
break;
case "µm":
length.Micrometers = value;
break;
case "pm":
length.Picometers = value;
break;
case "in":
length.Inches = value;
break;
case "ft":
length.Feet = value;
break;
case "yd":
length.Yards = value;
break;
case "mi":
length.Miles = value;
break;
case "smi":
length.ScandinavianMiles = value;
break;
case "ly":
length.LightYears = value;
break;
case "NM":
length.NauticalMiles = value;
break;
case "ftm":
length.Fathoms = value;
break;
case "fur":
length.Furlongs = value;
break;
case "ua":
length.AstronomicalUnits = value;
break;
case "pc":
length.Parsecs = value;
break;
default:
throw new ArgumentException("Not a valid unit given.", nameof(unitCode));
}
return length;
}
... }
Related
I'm currently learning C# and WPF, and i'm trying to simulate a circuit of logic gates and flipflops, but it won't work.
Could someone please show me a possible way to achive this? (maybe a simple similar application?)
What i have tried so far:
Class:
public class GateBase
{
public Type Type { get; set; }
public GateBase Input1 { get; set; }
public GateBase Input2 { get; set; }
public List<GateBase> Outputs { get; set; }
public bool Evaluated { get; set; }
public bool Value { get; set; }
public bool FlipFlop { get; set; }
public GateBase(Type type = Type.OFF, Gate input1 = null, Gate input2 = null)
{
Type = type;
Input1 = input1;
Input2 = input2;
Outputs = new List<GateBase>();
Evaluated = false;
Value = false;
FlipFlop = false;
switch (Type)
{
case Type.T:
case Type.D:
case Type.SR:
case Type.JK: FlipFlop = true; break;
}
}
public bool Evaluate()
{
if (!Evaluated)
{
bool input1 = false;
bool input2 = false;
if (Input1 != null)
{
if (Input1.FlipFlop)
input1 = Input1.Value;
else
input1 = Input1.Evaluate();
}
if (Input2 != null)
{
if (Input2.FlipFlop)
input2 = Input2.Value;
else
input2 = Input2.Evaluate();
}
switch (Type)
{
case Type.OFF:
Value = false; break;
case Type.ON:
Value = true; break;
case Type.OUT:
Value = input1; break;
case Type.CON:
Value = input1; break;
case Type.NOT:
Value = input1; break;
case Type.AND:
Value = input1 & input2; break;
case Type.OR:
Value = input1 | input2; break;
case Type.XOR:
Value = input1 ^ input2; break;
case Type.NAND:
Value = !(input1 & input2); break;
case Type.NOR:
Value = !(input1 | input2); break;
case Type.XNOR:
Value = !(input1 ^ input2); break;
case Type.D:
Value = input1; break;
case Type.T:
Value = input1 ? Value : !Value; break;
case Type.SR:
Value = (input1 ^ input2) ? Value : Value; break;
case Type.JK:
Value = (input1 ^ input2) ? input1 : (input1 & input2) ? !Value : Value; break;
default: Value = false; break;
}
}
Evaluated = true;
return Value;
}
public void ResetOutputs()
{
Evaluated = false;
foreach (Gate gate in Outputs)
{
if(!gate.FlipFlop)
{
gate.ResetOutputs();
}
}
}
}
Loop:
Update all logic gates
Update all flipflops and unevaluate outputs of each flipflop (if they are not a flipflop)
public List<GateBase> Gates { get; set; }
while (loop)
{
bool evaluating = true;
while (evaluating)
{
evaluating = false;
foreach (Gate gate in Gates)
{
switch (gate.Type)
{
case Model.Type.ON:
case Model.Type.OFF:
gate.Value = gate.Evaluate();
break;
case Model.Type.OUT:
case Model.Type.CON:
case Model.Type.NOT:
if (gate.Input1 != null && (gate.Input1.Evaluated || gate.Input1.FlipFlop))
{
gate.Value = gate.Evaluate();
}
break;
case Model.Type.AND:
case Model.Type.OR:
case Model.Type.XOR:
case Model.Type.NAND:
case Model.Type.NOR:
case Model.Type.XNOR:
if (gate.Input1 != null && gate.Input2 != null)
{
if ((gate.Input1.Evaluated || gate.Input1.FlipFlop) && (gate.Input2.Evaluated || gate.Input2.FlipFlop))
{
gate.Value = gate.Evaluate();
}
}
else
{
evaluating = true;
}
break;
}
}
}
evaluating = true;
while (evaluating)
{
evaluating = false;
foreach (Gate gate in Gates)
{
switch (gate.Type)
{
case Model.Type.D:
case Model.Type.T:
if (gate.Input1 != null && (gate.Input1.Evaluated || gate.Input1.FlipFlop))
{
gate.Value = gate.Evaluate();
gate.ResetOutputs();
}
else
{
evaluating = true;
}
break;
case Model.Type.SR:
case Model.Type.JK:
if (gate.Input1 != null && gate.Input2 != null)
{
if ((gate.Input1.Evaluated || gate.Input1.FlipFlop) && (gate.Input2.Evaluated || gate.Input2.FlipFlop))
{
gate.Value = gate.Evaluate();
gate.ResetOutputs();
}
}
else
{
evaluating = true;
}
break;
}
}
}
}
Problem:
If i'm using the JK-flipflop the results are not as expected. (but the T-flipflop works fine)
Here a link to the solution: Solution on GitHub
Thank You!
You have no break for your switch cases inside the while loop, so if the case is Model.Type.AND it will fall all the way down to the Model.Type.XNOR and I assume this isn't intended. This might be your problem (or at least a part of it).
Just to give you an idea, this small example will output "no break". x = 3 will output the string from default.
using System;
public class Program
{
public static void Main()
{
int x = 1;
switch(x){
case 0:
Console.WriteLine("Break");
break;
case 1:
case 2:
Console.WriteLine("no break");
break;
case 3:
default:
Console.WriteLine("End!");
break;
}
}
}
You can read more about the traditional switch here:
switch C# reference from Micrsoft
Now i fixed a problem and it's working much better than before. (i was resetting the gates before all flipflops were updated)
But it's still not working 100% correct...
Changes in the Loop:
// new list
List<Gate> gatesToResetOutputs = new List<Gate>();
while(loop)
{
while(evaluating gates)
{
...
}
while(evaluating flipflops)
{
...
// instead of
gate.ResetOutputs();
// replace with
gatesToResetOutputs.Add(gate);
...
}
// and at the end of the loop
foreach(Gate gate in gatesToResetOutputs)
{
gate.ResetOutputs();
}
}
I have the following json string:
[
{
"Key":"A",
"Value":null
},
{
"Key":"B",
"Value":"18"
},
{
"Key":"C",
"Value":"False"
},
{
"Key":"D",
"Value":"BOB"
}
]
I would like to be able to deserialize into the following objects:
public class ModelOne
{
public int? A { get; set; }
public int B { get; set;}
}
public class ModelTwo
{
public bool C { get; set; }
public string D { get; set; }
}
We thought about using var model = JsonConvert.DeserializeObject<ModelOne>(json); but clearly the json string is a list of Key and Value so that wouldn't work.
In an ideal world we would like to parse the json and match the Key to the Property Name and set the Value according to the property type. We could use a similar function to the above which accepts an anonymous type we're just not sure where to start so would be very greatful for some feedback and or assistance.
Thanks in advance.
EDIT:
The json array represents some data points we receive from an external api call.
ModelOne and ModelTwo are each view models in our MVC project we would like to pre-populate.
Thanks very much for all of your comments but notably both of #mjwills and #Heretic Monkey you really helped.
In the (end against my better judgement) I decided to use a little reflection.
public T ConvertDataMapToModel<T>(T item, List<Data> list)
{
Type itemType = typeof(T);
var response = (T)item;
var props = response.GetType().GetProperties();
foreach (var prop in props)
{
string propName = prop.Name;
string listValue = (string)(from c in list where c.Key == prop.Name select c.Value).FirstOrDefault();
if (!string.IsNullOrWhiteSpace(listValue) && !string.IsNullOrEmpty(listValue))
{
PropertyInfo pInstance = itemType.GetProperty(propName);
Type pInstancePropertyType = pInstance.PropertyType;
if (pInstancePropertyType.IsGenericType && pInstancePropertyType.GetGenericTypeDefinition() == typeof(Nullable<>))
{
pInstancePropertyType = pInstancePropertyType.GetGenericArguments()[0];
}
TypeCode typeCode = Type.GetTypeCode(pInstancePropertyType);
switch (typeCode)
{
case TypeCode.Boolean:
pInstance.SetValue(response, Convert.ToBoolean(listValue));
break;
case TypeCode.Byte:
pInstance.SetValue(response, Convert.ToByte(listValue));
break;
case TypeCode.Char:
pInstance.SetValue(response, Convert.ToChar(listValue));
break;
case TypeCode.DateTime:
pInstance.SetValue(response, Convert.ToDateTime(listValue));
break;
case TypeCode.DBNull:
pInstance.SetValue(response, Convert.DBNull);
break;
case TypeCode.Decimal:
pInstance.SetValue(response, Convert.ToDecimal(listValue));
break;
case TypeCode.Double:
pInstance.SetValue(response, Convert.ToDouble(listValue));
break;
case TypeCode.Empty:
pInstance.SetValue(response, "");
break;
case TypeCode.Int16:
pInstance.SetValue(response, Convert.ToInt16(listValue));
break;
case TypeCode.Int32:
pInstance.SetValue(response, Convert.ToInt32(listValue));
break;
case TypeCode.Int64:
pInstance.SetValue(response, Convert.ToInt64(listValue));
break;
case TypeCode.SByte:
pInstance.SetValue(response, Convert.ToSByte(listValue));
break;
case TypeCode.Single:
pInstance.SetValue(response, Convert.ToSingle(listValue));
break;
case TypeCode.String:
pInstance.SetValue(response, Convert.ToString(listValue));
break;
case TypeCode.UInt16:
pInstance.SetValue(response, Convert.ToUInt16(listValue));
break;
case TypeCode.UInt32:
pInstance.SetValue(response, Convert.ToUInt32(listValue));
break;
case TypeCode.UInt64:
pInstance.SetValue(response, Convert.ToUInt64(listValue));
break;
}
}
}
return response;
}
Today I created a factory for operator based Expression.
But when I create my factory, it has some dependency on comparison value.
Here is my code
public LambdaExpression GetPredicate(FieldType fieldType, GigFilterOption value)
{
switch (fieldType)
{
case FieldType.PriceNumeric :
return new OperatorFactory( Convert.ToDecimal(value.LowerLimit), Convert.ToDecimal(value.UpperLimit)).GetOperator((Operator)value.Operator).Apply<YayNinja.DAL.Task>("Price");
break;
case FieldType.TimePeriod :
return new OperatorFactory(Convert.ToDecimal(value.LowerLimit), Convert.ToDecimal(value.UpperLimit)).GetOperator((Operator)value.Operator).Apply<YayNinja.DAL.Task>("Duration");
break;
case FieldType.CheckBox:
case FieldType.Radio:
return new OperatorFactory(value.LowerLimit, value.UpperLimit).GetOperator((Operator)value.Operator).Apply<TaskField>("Value");
break;
default :
throw new NotImplementedException();
};
}
Here is My Operator factory.
public class OperatorFactory : IOperatoFactory
{
private object lowerLimit;
private object upperLimit;
public OperatorFactory(object _lowerLimit, object _upperLimit) //**here you see dependency of value that i need for comparsion.**
{
lowerLimit = _lowerLimit;
upperLimit = _upperLimit;
}
public IOperatorPredicate GetOperator(Operator #operator)
{
IOperatorPredicate operatorPredicate = null;
switch (#operator)
{
case Operator.Equal:
operatorPredicate = new EqualToPredicate(lowerLimit);
break;
case Operator.GreaterThan:
operatorPredicate = new GreaterThanPredicate(lowerLimit);
break;
case Operator.GreaterThanOrEqual:
operatorPredicate = new GreaterThanEqualPerdicate(lowerLimit);
break;
case Operator.LessThan:
operatorPredicate = new LessThanPredicate(lowerLimit);
break;
case Operator.LessThanOrEqual:
operatorPredicate = new LessThanEqualPredicate(lowerLimit);
break;
case Operator.Between:
operatorPredicate = new BetweenPredicate(lowerLimit,upperLimit);
break;
default:
throw new NotImplementedException();
}
return operatorPredicate;
}
}
I m sure that factory pattern is creator pattern it only create object without any dependency.
Please guide me on this topic
How will a C# switch statement's default label handle a nullable enum?
Will the default label catch nulls and any unhandled cases?
If it's null, it will hit the default label.
public enum YesNo
{
Yes,
No,
}
public class Program
{
public static void Main(string[] args)
{
YesNo? value = null;
switch (value)
{
case YesNo.Yes:
Console.WriteLine("Yes");
break;
case YesNo.No:
Console.WriteLine("No");
break;
default:
Console.WriteLine("default");
break;
}
}
}
The program will print default.
Unless null is handled.
public class Program
{
public static void Main(string[] args)
{
YesNo? value = null;
switch (value)
{
case YesNo.Yes:
Console.WriteLine("Yes");
break;
case YesNo.No:
Console.WriteLine("No");
break;
case null:
Console.WriteLine("NULL");
break;
default:
Console.WriteLine("default");
break;
}
}
}
prints NULL.
If you have an unhandled enum value that was added later:
public enum YesNo
{
Yes,
No,
FileNotFound,
}
public class Program
{
public static void Main(string[] args)
{
YesNo? value = YesNo.FileNotFound;
switch (value)
{
case YesNo.Yes:
Console.WriteLine("Yes");
break;
case YesNo.No:
Console.WriteLine("No");
break;
default:
Console.WriteLine("default");
break;
}
}
}
It still prints default.
You can use the null-coalescing operator ?? to route null switch values to a specific case label other than default:
public static IEnumerable<String> AsStrings(this IEnumerable<Char[]> src)
{
Char[] rgch;
var e = src.GetEnumerator();
while (e.MoveNext())
{
switch ((rgch = e.Current)?.Length ?? -1)
{
case -1: // <-- value when e.Current is 'null'
yield return null;
break;
case 0:
yield return String.Empty;
break;
case 1:
yield return String.Intern(new String(rgch[0], 1));
break;
default: // 2...n
yield return new String(rgch);
break;
}
}
}
You can have a case for null.
switch (MyNullableEnum)
{
case Option1:
break;
case Option2:
break;
case Option3:
break;
case null:
break;
default:
break;
}
It's worth to mention that C# 8.0 introduced a new Property Pattern for a switch expression. Now you can implement default logic to switch by using underscore:
public double Calculate(int left, int right, Operator op) =>
op switch
{
Operator.PLUS => left + right,
Operator.MINUS => left - right,
Operator.MULTIPLY => left * right,
Operator.DIVIDE => left / right,
_ => 0 // default
}
Ref. https://learn.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-8
I'm working with a database that is only capable of supporting data types that I have written code for.
I created an Enum parameter with a list of available types.
public enum TableDataType
{
None=0, String=1, Integer=2, Character=3, Boolean=4, DateTime=5, Decimal=6
}
This works, but I still have to process going in and coming back out of my data structures:
TableDataType GetMyType(DataGridViewColumn col) {
TableDataType type;
if (col.ValueType == typeof(bool)) {
type = TableDataType.Boolean;
} else if (col.ValueType == typeof(char)) {
type = TableDataType.Character;
} else if (col.ValueType == typeof(DateTime)) {
type = TableDataType.DateTime;
} else if (col.ValueType == typeof(Decimal)) {
type = TableDataType.Decimal;
} else if (col.ValueType == typeof(Int32)) {
type = TableDataType.Integer;
} else if (col.ValueType == typeof(string)) {
type = TableDataType.String;
} else {
throw new ArgumentException(string.Format("Data Type of '{0}' is not supported.", col.ValueType));
}
return type;
}
Then there is code going the other way...
Type GetSystemType(TableDataType myType) {
Type sysType;
switch (myType) {
case TableDataType.Boolean: sysType = typeof(bool); break;
case TableDataType.Character: sysType = typeof(char); break;
case TableDataType.DateTime: sysType = typeof(DateTime); break;
case TableDataType.Integer: sysType = typeof(Int32); break;
case TableDataType.Decimal: sysType = typeof(Decimal); break;
case TableDataType.String: sysType = typeof(string); break;
default: throw new ArgumentOutOfRangeException(string.Format("Data Type '{0}' is not allowed.", cd.DataType));
}
return sysType;
}
The problem comes from using routines similar to these at more than one spot in my code. If I tell a DataGridViewColumn that it is formatted for an Int32 then pass it an Integer, I get ArgumentException errors.
I'm looking for a good, fast class wrapper that cleverly stores the value and a select range of acceptable data types.
[EDIT] Solution I came up with:
Using the information provided in harpo's comment and Bas's solution, I created this class:
public static class Enumerate {
private Enumerate() {
throw new NotSupportedException();
}
public static SqlDbType ForSqlCe(System.Type item) {
return sqlDbCode(item);
}
public static SqlDbType ForSqlCe(TableDataType item) {
return sqlDbCode(item.GetType());
}
static SqlDbType sqlDbCode(System.Type item) {
switch (Type.GetTypeCode(item)) {
case TypeCode.Boolean: return SqlDbType.Bit;
case TypeCode.Byte:
case TypeCode.Char:
case TypeCode.SByte: return SqlDbType.NChar;
case TypeCode.DateTime: return SqlDbType.DateTime;
case TypeCode.Decimal:
case TypeCode.Double:
case TypeCode.Single: return SqlDbType.Decimal;
case TypeCode.Int16:
case TypeCode.Int32:
case TypeCode.Int64:
case TypeCode.UInt16:
case TypeCode.UInt32:
case TypeCode.UInt64: return SqlDbType.Int;
case TypeCode.String: return SqlDbType.NVarChar;
case TypeCode.DBNull:
case TypeCode.Empty:
case TypeCode.Object:
default: throw new TypeAccessException(item + " unknown");
}
}
public static TableDataType ForTableData(SqlDbType item) {
return tableDataCode(item.GetType());
}
public static TableDataType ForTableData(System.Type item) {
return tableDataCode(item);
}
static TableDataType tableDataCode(System.Type item) {
switch (Type.GetTypeCode(item)) {
case TypeCode.Boolean: return TableDataType.Boolean;
case TypeCode.Byte:
case TypeCode.Char:
case TypeCode.SByte: return TableDataType.Character;
case TypeCode.DateTime: return TableDataType.DateTime;
case TypeCode.Decimal:
case TypeCode.Double:
case TypeCode.Single: return TableDataType.Decimal;
case TypeCode.Int16:
case TypeCode.Int32:
case TypeCode.Int64:
case TypeCode.UInt16:
case TypeCode.UInt32:
case TypeCode.UInt64: return TableDataType.Integer;
case TypeCode.String: return TableDataType.String;
case TypeCode.DBNull:
case TypeCode.Empty:
case TypeCode.Object:
default: throw new TypeAccessException(item + " unknown");
}
}
public static Type ForWin32(string item) {
string text = item.Trim().ToLower();
switch (text) {
case "boolean":
case "bool":
case "bit": return typeof(bool);
case "byte":
case "char":
case "sbyte": return typeof(char);
case "date":
case "datetime":
case "time": return typeof(DateTime);
case "decimal":
case "double":
case "numeric":
case "single": return typeof(Double);
case "int":
case "int16":
case "int32":
case "int64":
case "integer":
case "uint16":
case "uint32":
case "uint64": return typeof(Int32);
case "string": return typeof(string);
default:
throw new TypeAccessException(item + " unknown");
}
}
public static Type ForWin32(SqlDbType item) {
return win32Code(item.GetType());
}
public static Type ForWin32(TableDataType item) {
return win32Code(item.GetType());
}
static Type win32Code(System.Type item) {
switch (Type.GetTypeCode(item)) {
case TypeCode.Boolean: return typeof(bool);
case TypeCode.Byte:
case TypeCode.Char:
case TypeCode.SByte: return typeof(char);
case TypeCode.DateTime: return typeof(DateTime);
case TypeCode.Decimal:
case TypeCode.Double:
case TypeCode.Single: return typeof(Decimal);
case TypeCode.Int16:
case TypeCode.Int32:
case TypeCode.Int64:
case TypeCode.UInt16:
case TypeCode.UInt32:
case TypeCode.UInt64: return typeof(Int32);
case TypeCode.String: return typeof(string);
case TypeCode.DBNull:
case TypeCode.Empty:
case TypeCode.Object:
default: throw new TypeAccessException(item + " unknown");
}
}
}
If you dont want to use System.TypeCode like harpo suggests, use Type.GetType():
string assemblyQualifiedName = "System.{0}, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089";
string typeString = myEnumValue.ToString();
Type type = Type.GetType(string.Format(assemblyQualifiedName, typeString));
Another option is to store the mapping in a Dictionary:
static class TypeResolver
{
static Dictionary<TableDataType, Type> typeLookup = new Dictionary<TableDataType, Type>();
static TypeResolver()
{
typeLookup.Add(TableDataType.Integer, typeof(Int32));
typeLookup.Add(TableDataType.String, typeof(String));
}
public static Type Resolve(TableDataType tableType)
{
return typeLookup[tableType];
}
}