I want to do an application that pareses text. So far, I have a class called Result, that holds the value and type each part of an equation.
public enum ResultType
{
Int32,
Double,
Boolean,
Color,
DateTime,
String,
Undefined,
Void
}
public class Result
{
public object Value { get; set; }
public ResultType Type { get; set; }
}
Possible Result's could be:
5 : Int32
true : Boolean
DADACC : Color
"Hello World!" : String
10.0 : Double
13/11/1986 : DateTime
Now I want to sum/divide/pow/... two Results but I really don´t want to do all the work. In C#, you can mix them all together and get an answer.
var value = "Hello" + 2.0 + 4 + DateTime.Today; (value = "Hello2413/09/2011 12:00:00 a.m.")
Is there an easy way to handle this? Or do I have to figure out all combos by myself? I´m thinking about something like:
var Operator = "+"; // or "-","*","/","^","%"
var sum = DoTheCSharpOperation(Operator, ResultA.Value, ResultB.Value)
var sumResult = new Result(sum);
This sounds to me like a perfect application for the "dynamic" keyword:
using System;
using System.Diagnostics;
namespace ConsoleApplication33 {
public static class Program {
private static void Main() {
var result1=DoTheCSharpOperation(Operator.Plus, 1.2, 2.4);
var result2=DoTheCSharpOperation(Operator.Plus, "Hello", 2.4);
var result3=DoTheCSharpOperation(Operator.Minus, 5, 2);
Debug.WriteLine(result1); //a double with value 3.6
Debug.WriteLine(result2); //a string with value "Hello2.4"
Debug.WriteLine(result3); //an int with value 3
}
public enum Operator {
Plus,
Minus
}
public static object DoTheCSharpOperation(Operator op, dynamic a, dynamic b) {
switch(op) {
case Operator.Plus:
return a+b;
case Operator.Minus:
return a-b;
default:
throw new Exception("unknown operator "+op);
}
}
}
}
Related
---Post updated after to many errors found on first code---
I have some trouble with Boolean on Object.
This is my Chunk class containing a Zone struct :
using System;
using System.Collections.Generic;
public class Test
{
public static void Main()
{
new Chunk();
}
}
public class Chunk {
List <Zone> zones;
public Chunk() {
// Create 3 elements on the List
this.zones = new List<Zone>();
this.zones.Add(new Zone(1));
this.zones.Add(new Zone(2));
this.zones.Add(new Zone(42));
// Add coord to 2th zones
this.zones[0].AddCoord(1);
Console.WriteLine("Count : " + this.zones[0].coords.Count); // -> Count: 1
// Now with bool - NOT WORKING
this.zones[0].SetBool();
Console.WriteLine("Bool: " + this.zones[0].isOnChunkBorder ); // -> Bool: False
// Now with bool - WORKING
this.zones[0] = this.zones[0].SetBoolAndReturnThis();
Console.WriteLine("Bool: " + this.zones[0].isOnChunkBorder ); // -> Bool: True
}
public struct Zone {
public bool isOnChunkBorder;
public List<int> coords;
public Zone(int firstCoord) {
this.coords = new List<int>();
this.coords.Add(firstCoord);
this.isOnChunkBorder = false;
}
public void AddCoord(int coord) {
this.coords.Add(coord);
}
public void SetBool() {
this.isOnChunkBorder = true;
}
public Zone SetBoolAndReturnThis() {
this.isOnChunkBorder = true;
return this;
}
}
}
I don't know why struct boolean are not updated when I'm using a simple update, but works fine is Zone is replaced by Class or if the struct is returned ?
The effect you observe caused by the Zone being a struct.
Structs are value types and are copied on assignment.
Is it possible to simplify this logic, Is there generic way to do it.
The code finds marked attributes and parses it according to the attribute type.
Please suggest some way to optimize this code, all the data type of Product class will be string, I'm getting product input as xml directly converting serialized data to a class with decimal,int,float will not give proper error message, If there is list of item it throws error in xml we wont know which row has caused the error.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
namespace TestSolution
{
public interface ICustomParser
{
bool Parse(string input);
}
public class DecimalParserAttribute : Attribute, ICustomParser
{
public bool Parse(string input)
{
if (input == null) return false;
decimal decimalValue;
return decimal.TryParse(input, out decimalValue);
}
}
public class intParserAttribute : Attribute, ICustomParser
{
public bool Parse(string input)
{
if (input == null) return false;
int intValue;
return int.TryParse(input, out intValue);
}
}
public class Product
{
[DecimalParser]
public string Weight { get; set; }
[intParser]
public string NoOfItems { get; set; }
[intParser]
public string GRodes { get; set; }
[intParser]
public string WRodes { get; set; }
}
class Program
{
static void Main(string[] args)
{
var sb = Validate(new Product() { NoOfItems = "1", GRodes = "4", Weight = "5", WRodes = "23" });
Console.WriteLine(sb);
sb = Validate(new Product() { NoOfItems = "1", GRodes = "4w", Weight = "5", WRodes = "23" });
Console.WriteLine(sb);
Console.ReadKey();
}
private static string Validate(Product product)
{
var sb = new StringBuilder();
foreach (var property in product.GetType().GetProperties())
{
var value = Convert.ToString(property.GetValue(product, null));
var sel = property.GetAttribute<ICustomParser>();
if (sel == null) continue;
var parserinstance = (ICustomParser)Activator.CreateInstance(sel.GetType());
if (parserinstance.Parse(value)) continue;
sb.AppendLine(string.Format("{0} Has invalid value", property.Name));
}
return sb.ToString();
}
}
public static class Extensions
{
public static T GetAttribute<T>(this PropertyInfo property)
{
return (T)property.GetCustomAttributes(false).Where(s => s is T).FirstOrDefault();
}
}
}
If you only have one type (Product), it probably isn't worth it - just write the validation code explicitly without all the fancy stuff. If, however, you have multiple types to inspect (perhaps known only at runtime):
It really depends how fast it needs to be. How often does this run? If it is periodic, then there isn't a vast amount to do - the main change would be to just cast the parser directly:
var parserInstance = (ICustomParser)sel;
(it already is the attribute type)
If it is critical path, then there is a lot you can do to beef it up, but you get into the realm of metaprogramming - which is essentially what most tools like serializers and ORMs do to reduce runtime reflection. If you're not familiar with hacking IL at runtime, I would recommend looking at a tool like "Sigil" (available on nuget) that makes it hard to get wrong (or at least: tells you what you've done wrong). Essentially, you can inspect the data structure and then emit the IL that matches what it would look like if you were doing it all in explicit code; for example, emitting IL that looks kinda like:
static readonly DecimalParserAttribute _decimal = new DecimalParserAttribute();
public static void Validate(Product product) {
var sb = new StringBuilder();
if(!_decimal.Parse(product.Weight)) {
sb.Append(...);
}
// ... etc
...,
}
I would like to create a method that uses the keyword in instead of a comma to separate parameters in a method declaration; something similar to the foreach(a in b) method.
Example
Class Structure
public class Length
{
public double Inches;
public double Feet;
public double Yards;
public enum Unit { Inch, Foot, Yard }
Dictionary<Unit, double> inchFactor = new Dictionary<Unit, double>()
{
{ Unit.Inch, 1 },
{ Unit.Foot, 12 },
{ Unit.Yard, 36 }
};
public Length(double value, Unit unit)
{
this.Inches = value * inchFactor[unit];
this.Feet = this.Inches / inchFactor[Unit.Foot];
this.Yards = this.Inches / inchFactor[Unit.Yard];
}
}
Method Definition in Class
// I'd like to know how to use "in" like this ↓
public List<Length> MultiplesOf(Length divisor in Length dividend)
{
double inchEnumeration = divisor.Inches;
List<Length> multiples = new List<Length>();
while (inchEnumeration <= dividend.Inches)
{
multiples.Add(new Length(inchEnumeration, Length.Unit.Inch));
inchEnumeration += divisor.Inches;
}
return multiples;
}
Ideal Implementation
private void DrawRuler()
{
Length eighthInch = new Length(0.125, Length.Unit.Inch);
Length oneFoot = new Length(1, Length.Unit.Foot);
// Awesome.
List<Length> tickGroup = Length.MultiplesOf(eighthInch in oneFoot);
double inchPixels = 10;
foreach (Length tick in tickGroup)
{
// Draw ruler.
}
}
I've looked into creating new keywords, but it looks like C# does not support defining keywords.
As has been mentioned in the comments, you cannot define custom keywords in C# (unless you extend the compiler, which is an advanced task). However, if your goal is to clarify the meaning of the two arguments, then I would suggest using named arguments instead:
// Define the method as usual:
public List<Length> MultiplesOf(Length divisor, Length dividend)
{
// ...
}
// Then call it like so, explicitly showing what is the divisor and the dividend:
List<Length> tickGroup = Length.MultiplesOf(divisor: eighthInch, dividend: oneFoot);
While you can't redefine an existing keyword, there is other way to accomplish what you in a slightly different way using Fluent Interface :
public class Length
{
// ...
public static IFluentSyntaxProvider MultiplesOf(Length divisor)
{
return new FluentSyntaxProvider(divisor);
}
public interface IFluentSyntaxProvider
{
List<Length> In(Length dividend);
}
private class FluentSyntaxProvider : IFluentSyntaxProvider
{
private Length divisor;
public FluentSyntaxProvider(Length divisor)
{
this.divisor = divisor;
}
public List<Length> In(Length dividend)
{
double inchEnumeration = divisor.Inches;
List<Length> multiples = new List<Length>();
while (inchEnumeration <= dividend.Inches)
{
multiples.Add(new Length(inchEnumeration, Length.Unit.Inch));
inchEnumeration += divisor.Inches;
}
return multiples;
}
}
}
Example of usage :
// Awesome.
List<Length> tickGroup = Length.MultiplesOf(eighthInch).In(oneFoot);
I would like an advice. My project have a lot of equals methods with different values, and i would like to do a single method that does the same.
The methods are this:
private void Enum1()
{
Console.WriteLine(Enum.GetValue(ENUM1.Code));
Console.WriteLine(Enum.GetValue(ENUM1.Info));
}
private void Enum2()
{
Console.WriteLine(Enum.GetValue(ENUM2.Code));
Console.WriteLine(Enum.GetValue(ENUM2.Info));
}
private void Enum3()
{
Console.WriteLine(Enum.GetValue(ENUM3.Code));
Console.WriteLine(Enum.GetValue(ENUM3.Info));
}
This is the enums:
public enum ENUM1
{
Code = 1,
Info = 3
}
public enum ENUM2
{
Code = 91,
Info = 4
}
public enum ENUM3
{
Code = 6,
Info = 27
}
There is only a way to create a method by inserting the input type of enum to use? maybe a similar solution of this:
private void General("ENUM1")
{
var type = ENUM1;
switch (p)
{
case "ENUM1":
type = ENUM1;
case "ENUM2":
type = ENUM2;
case "CASALINGHI":
type = ENUM3;
default:
type = ENUM1;
}
Console.WriteLine(Enum.GetValue(type.Code));
Console.WriteLine(Enum.GetValue(type.Info));
}
I think something like this is what you are looking for:
private void General<T>()
{
var values = Enum.GetValues(typeof(T));
foreach(var value in values)
Console.WriteLine(value);
}
General<Enum1>();
General<Enum2>();
General<Enum3>();
Or this, depending on how you want to use it:
private void General(Type enumType)
{
var values = Enum.GetValues(enumType);
foreach(var value in values)
Console.WriteLine(value);
}
General(typeof(Enum1));
General(typeof(Enum2));
General(typeof(Enum3));
Why do you keep using enums, when you can easily use classes? Read more about Object-Oriented programming.
Create a single class:
public class MyEnum
{
public int Code
{
get; set;
}
public int Info
{
get; set;
}
public string Display()
{
Console.WriteLine(this.Code);
Console.WriteLine(this.Info)
}
//
// This will keep your enums static, available from any method
//
private static List<MyEnum> _globals = new List<MyEnum();
public static List<MyEnum> Globals ()
{
if (this._globals.Count == 0)
{
this._globals.Add(new MyEnum(){ Code = 1, Info = 3 });
this._globals.Add(new MyEnum(){ Code = 91, Info = 4 });
this._globals.Add(new MyEnum(){ Code = 6, Info = 27 });
}
return this._globals;
}
}
After this you can easily print out all the enums with the following code:
foreach (MyEnum* en in MyEnum.Globals())
{
en.Display();
}
Please look into solutions similar to this one, since your enum's obviously represent some data.
This question already has answers here:
Enum ToString with user friendly strings
(25 answers)
Using [Display(Name = "X")] with an enum. Custom HtmlHelper in MVC3 ASP.Net
(3 answers)
Closed 9 years ago.
Tried setting up an enum that has spaces in attributes but was very hard so figured their might be an easy way to hack this with a string format or something since their is only one enum that I need that has spaces and I know exactly what it is. Any helping wiht adding a space to this string
public class Address
{
...blah...more class datatypes here...
public AddressType Type { get; set; } //AddressType is an enum
...blah....
}
if (Address.Type.ToString() == "UnitedStates")
{
**Add space between United and States**
}
If your enum entries are in camel case, you can insert a whitespace before the upper letter
string res = Regex.Replace("UnitedStates", "[A-Z]", " $0").Trim();
You can create your own ToString method on the enumeration using an extension method.
public static class AddressTypeExtensions
{
public static string ToMyString(this AddressType addressType)
{
if (addressType == AddressType.UnitedStates)
return "United States";
return addressType.ToString();
}
}
This is a neat trick I found yesterday (in 2009). I wonder why I never thought of it myself. In the .net framework there is no way how to control .ToString() for enumerations. To work around that an extension method can be created as well as an attribute to decorate the different values of the enumeration. Then we can write something like this:
public enum TestEnum
{
[EnumString("Value One")]
Value1,
[EnumString("Value Two")]
Value2,
[EnumString("Value Three")]
Value3
}
EnumTest test = EnumTest.Value1;
Console.Write(test.ToStringEx());
The code to accomplish this is pretty simple:
[AttributeUsage(AttributeTargets.Field)]
public class EnumStringAttribute : Attribute
{
private string enumString;
public EnumStringAttribute(string EnumString)
{
enumString = EnumString;
}
public override string ToString()
{
return enumString;
}
}
public static class ExtensionMethods
{
public static string ToStringEx(this Enum enumeration)
{
Type type = enumeration.GetType();
FieldInfo field = type.GetField(enumeration.ToString());
var enumString =
(from attribute in field.GetCustomAttributes(true)
where attribute is EnumStringAttribute
select attribute).FirstOrDefault();
if (enumString != null)
return enumString.ToString();
// otherwise...
return enumeration.ToString();
}
}
[TestMethod()]
public void ToStringTest()
{
Assert.AreEqual("Value One", TestEnum.Value1.ToStringEx());
Assert.AreEqual("Value Two", TestEnum.Value2.ToStringEx());
Assert.AreEqual("Value Three", TestEnum.Value3.ToStringEx());
}
The credit goes to this post.
I have a handy Extension method for exactly this
public static class EnumExtensions
{
public static string ToNonPascalString(this Enum enu)
{
return Regex.Replace(enu.ToString(), "([A-Z])", " $1").Trim();
}
public T EnumFromString<T>(string value) where T : struct
{
string noSpace = value.Replace(" ", "");
if (Enum.GetNames(typeof(T)).Any(x => x.ToString().Equals(noSpace)))
{
return (T)Enum.Parse(typeof(T), noSpace);
}
return default(T);
}
}
Example:
public enum Test
{
UnitedStates,
NewZealand
}
// from enum to string
string result = Test.UnitedStates.ToNonPascalString(); // United States
// from string to enum
Test myEnum = EnumExtensions.EnumFromString<Test>("New Zealand"); // NewZealand
The following code will convert AbcDefGhi to Abc Def Ghi.
public static string ConvertEnum(this string value)
{
string result = string.Empty;
char[] letters = value.ToCharArray();
foreach (char c in letters)
if (c.ToString() != c.ToString().ToLower())
result += " " + c;
else
result += c.ToString();
return result;
}