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();
}
}
Related
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;
}
I am using the HtmlSanitizer to Sanitize the url as well as the html. When I am passing the & from the UI the Sanitize converts to &
I want to allow the & to be get passed in the model. I used the below code from the api
_sanitizer.AllowedSchemes.Add("&");
complete code
public void SetValue(object target, object value)
{
if (value is string s)
{
_sanitizer.AllowedSchemes.Add("&");
var encodedString = _sanitizer.Sanitize(s);
_targetProperty.SetValue(target, encodedString);
}
else
{
// Shouldn't get here as we checked for string properties before setting this value provider
_targetProperty.SetValue(target, value);
}
}
The above code conver the & to &. Is there any way to allow & in the HtmlSanitizer
References
https://github.com/mganss/HtmlSanitizer
Found the solution after the research. Create a custom html mapper
private string Sanitize(string text)
{
return Sanitizer.Sanitize(text, "", NoEntityMarkupFormatter.Instance);
}
private class NullEntityResolver : IEntityProvider
{
public string GetSymbol(string name)
{
return null;
}
}
private class NoEntityMarkupFormatter : IMarkupFormatter
{
internal static readonly NoEntityMarkupFormatter Instance = new NoEntityMarkupFormatter();
private static readonly IMarkupFormatter defaultFormatter = HtmlMarkupFormatter.Instance;
public string Text(string text)
{
StringBuilder sb = new StringBuilder();
for (int i = 0; i < text.Length; i++)
switch (text[i])
{
// Change: Don't do this as we aren't decoding incoming entities
// case '&': sb.Append("&"); break;
case '\xA0': sb.Append(" "); break;
case '>': sb.Append(">"); break;
case '<': sb.Append("<"); break;
default: sb.Append(text[i]); break;
}
return sb.ToString();
}
public string Comment(IComment comment)
{
return defaultFormatter.Comment(comment);
}
public string Processing(IProcessingInstruction processing)
{
return defaultFormatter.Processing(processing);
}
public string Doctype(IDocumentType doctype)
{
return defaultFormatter.Doctype(doctype);
}
public string OpenTag(IElement element, bool selfClosing)
{
var sb = new StringBuilder();
sb.Append('<');
if (!string.IsNullOrEmpty(element.Prefix))
sb.Append(element.Prefix).Append(':');
sb.Append(element.LocalName);
foreach (var attribute in element.Attributes)
sb.Append(" ").Append(Instance.Attribute(attribute));
sb.Append('>');
return sb.ToString();
}
public string CloseTag(IElement element, bool selfClosing)
{
return defaultFormatter.CloseTag(element, selfClosing);
}
public string Attribute(IAttr attr)
{
var namespaceUri = attr.NamespaceUri;
var localName = attr.LocalName;
var value = attr.Value;
var sb = new StringBuilder();
if (string.IsNullOrEmpty(namespaceUri))
sb.Append(localName);
else if (Is(namespaceUri, NamespaceNames.XmlUri))
sb.Append(NamespaceNames.XmlPrefix).Append(':').Append(localName);
else if (Is(namespaceUri, NamespaceNames.XLinkUri))
sb.Append(NamespaceNames.XLinkPrefix).Append(':').Append(localName);
else if (Is(namespaceUri, NamespaceNames.XmlNsUri))
sb.Append(XmlNamespaceLocalName(localName));
else
sb.Append(attr.Name);
sb.Append('=').Append('"');
for (var i = 0; i < value.Length; i++)
switch (value[i])
{
// Change: Don't do this as we aren't decoding incoming entities
// case '&': temp.Append("&"); break;
case '\xA0': sb.Append(" "); break;
case '"': sb.Append("""); break;
default: sb.Append(value[i]); break;
}
return sb.Append('"').ToString();
}
private static bool Is(string a, string b)
{
return string.Equals(a, b, StringComparison.Ordinal);
}
private static string XmlNamespaceLocalName(string name)
{
return Is(name, NamespaceNames.XmlNsPrefix) ? name : string.Concat(NamespaceNames.XmlNsPrefix, ":");
}
}
private static readonly Configuration TextWithoutEntityConfiguration =
new Configuration().WithCss(e => e.Options = new CssParserOptions
{
IsIncludingUnknownDeclarations = true,
IsIncludingUnknownRules = true,
IsToleratingInvalidConstraints = true,
IsToleratingInvalidValues = true
}).With(new NullEntityResolver());
private static readonly HtmlSanitizer Sanitizer = new HtmlSanitizer
{
HtmlParserFactory = () => new HtmlParser(TextWithoutEntityConfiguration)
};
Reference
https://gist.github.com/nallar/d91160cd6a30b15ccb5265677f0cf29a
I have the need to examine to see if an object can be converted to a specific DataType or not, and came up with this :
public static bool TryParseAll(System.Type typeToConvert, object valueToConvert)
{
bool succeed = false;
switch (typeToConvert.Name.ToUpper())
{
case "DOUBLE":
double d;
succeed = double.TryParse(valueToConvert.ToString(), out d);
break;
case "DATETIME":
DateTime dt;
succeed = DateTime.TryParse(valueToConvert.ToString(), out dt);
break;
case "INT16":
Int16 i16;
succeed = Int16.TryParse(valueToConvert.ToString(), out i16);
break;
case "INT":
Int32 i32;
succeed = Int32.TryParse(valueToConvert.ToString(), out i32);
break;
case "INT32":
Int32 i322;
succeed = Int32.TryParse(valueToConvert.ToString(), out i322);
break;
case "INT64":
Int64 i64;
succeed = Int64.TryParse(valueToConvert.ToString(), out i64);
break;
case "BOOLEAN":
bool b;
succeed = Boolean.TryParse(valueToConvert.ToString(), out b);
break;
case "BOOL":
bool b1;
succeed = bool.TryParse(valueToConvert.ToString(), out b1);
break;
}
return succeed;
}
I'm wondering is there any ways other than this? Which is more dynamic and more efficient?
Thanks!
You should use the TypeDescriptor class:
public static T Convert<T>(this string input)
{
var converter = TypeDescriptor.GetConverter(typeof(T));
if(converter != null)
{
//Cast ConvertFromString(string text) : object to (T)
return (T)converter.ConvertFromString(input);
}
return default(T);
}
of course this will throw an exception if the conversion fails so you will want to try/catch it.
Here is my version of generic TryParse method.
I believe you can use this version too:
double pi;
if(ValueTypeHelper.TryParse("3.14159", out pi)) {
// .. pi = 3.14159
}
...
string eStr = "2.71828";
float e;
if(eStr.TryParse(out e)) {
// .. e = 2.71828f
}
...
static class ValueTypeHelper {
static IDictionary<Type, Delegate> cache = new Dictionary<Type, Delegate>();
public static bool TryParse<T>(this string valueStr, out T result) {
Delegate d = null;
if(!cache.TryGetValue(typeof(T), out d)) {
var mInfos = typeof(T).GetMember("TryParse", MemberTypes.Method, BindingFlags.Static | BindingFlags.Public);
if(mInfos.Length > 0) {
var s = Expression.Parameter(typeof(string));
var r = Expression.Parameter(typeof(T).MakeByRefType());
d = Expression.Lambda<TryParseDelegate<T>>(
Expression.Call(mInfos[0] as MethodInfo, s, r), s, r).Compile();
}
cache.Add(typeof(T), d);
}
result = default(T);
TryParseDelegate<T> tryParse = d as TryParseDelegate<T>;
return (tryParse != null) && tryParse(valueStr, out result);
}
delegate bool TryParseDelegate<T>(string valueStr, out T result);
}
I have combined both DmitryG's and RezaRahmati's suggested solutions:
static class GenericValueConverter
{
public static bool TryParse<T>(this string input, out T result)
{
bool isConversionSuccessful = false;
result = default(T);
var converter = TypeDescriptor.GetConverter(typeof(T));
if (converter != null)
{
try
{
result = (T)converter.ConvertFromString(input);
isConversionSuccessful = true;
}
catch { }
}
return isConversionSuccessful;
}
}
void Main()
{
double pi;
if (GenericValueConverter.TryParse("3,14159", out pi)) //Use right decimal point seperator for local culture
{
pi.Dump(); //ConsoleWriteline for LinqPad
//pi=3,14159
}
string dtStr = "2016-12-21T16:34:22";
DateTime dt;
if (dtStr.TryParse(out dt))
{
dt.Dump(); //ConsoleWriteline for LinqPad
//dt=21.12.2016 16:34:22
}
string guidStr = "D430831B-03B0-44D5-A971-4E73AF96B5DF";
Guid guid;
if (guidStr.TryParse(out guid))
{
guid.Dump(); //ConsoleWriteline for LinqPad
//guid=d430831b-03b0-44d5-a971-4e73af96b5df
}
}
Does there exist any c# type/structure that enables a variable turning into a constant?
Maybe by setting a flag which fixes the value.
Example code:
foreach (Person p in group)
{
if (p.Mood.Equals("bad"))
{
group.Mood = "bad";
group.Mood.Fix(); // This should disable any further changing on group.Mood
}
else
{
group.Mood = "good";
}
}
The mood of the whole group should be "bad" if one persons mood is bad.
I know that I can implement something like this by myself but I use it that often that I can imaging that such a structure already exists.
I hope you're all in a good mood! ;)
No, the variable is made constant upon declaration. However, you could get something close with a property setter:
public string Mood
{
set
{
if(mood != "Bad")
mood = value;
}
}
I would advice against doing this for the following reasons:
A property with a setter should be allowed to be set
A property with a setter should not simply ignore the value given to it
Secondly, why do you even look at more people in your collection if you've already established the final value?
I would instead change the code into one of the three following variants:
group.Mood = "good";
foreach (Person p in group)
{
if (p.Mood.Equals("bad"))
{
group.Mood = "bad";
break;
}
}
or this:
string groupMood = "good";
foreach (Person p in group)
{
if (p.Mood.Equals("bad"))
{
groupMood = "bad";
break;
}
}
group.Mood = groupMood;
or this:
if (group.Any(p => p.Mood == "bad"))
group.Mood = "bad";
else
group.Mood = "good";
If instead you want such a "Popsicle" type, here's one which you can try with LINQPad:
void Main()
{
var i = new Popsicle<int>(10);
i.Value = 25;
i.Value = 33;
i.Dump();
i.Freeze(FrozenBehavior.IgnoreNewValues);
i.Value = 17;
i.Dump();
i = new Popsicle<int>(10);
i.Freeze(FrozenBehavior.ThrowException);
i.Value = 17;
i.Dump();
}
public class Popsicle<T>
{
private T _Value;
private FrozenBehavior? _FrozenBehavior;
public Popsicle(T value = default(T))
{
_Value = value;
}
public T Value
{
get
{
return _Value;
}
set
{
if (_FrozenBehavior.HasValue)
{
switch (_FrozenBehavior.GetValueOrDefault())
{
case FrozenBehavior.IgnoreNewValues:
break;
case FrozenBehavior.ThrowException:
throw new InvalidOperationException("This Popsicle<T> has been frozen and configured to throw exceptions if an attempt is made to change its value");
default:
throw new InvalidOperationException("This Popsicle<T> is in an invalid frozen state");
}
}
else
_Value = value;
}
}
public void Freeze(FrozenBehavior behavior = FrozenBehavior.ThrowException)
{
if (!_FrozenBehavior.HasValue)
_FrozenBehavior = behavior;
else
throw new InvalidOperationException("This Popsicle<T> has already been frozen, cannot re-freeze");
}
public override string ToString()
{
if (!_FrozenBehavior.HasValue)
return _Value + " (unfrozen)";
else switch (_FrozenBehavior)
{
case FrozenBehavior.IgnoreNewValues:
return _Value + " (frozen: ignore)";
case FrozenBehavior.ThrowException:
return _Value + " (frozen: throw)";
default:
throw new InvalidOperationException("This Popsicle<T> is in an invalid frozen state");
}
}
}
public enum FrozenBehavior
{
IgnoreNewValues,
ThrowException
}
With LinQ this can be done in a short way. Check if there is any person that has a bad mood, if so set the group-mood to bad, otherwise good.
group.Mood = group.Any(p => p.Mood == "bad") ? "bad" : "good";
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