Does exist to make short code which i can replace if() argument for example:
int x = 1; // x can be 1,2,3 etc.
if(x==1 || x==3 || x==12)
{
//do something..
}
I don't want to repeat x==1, x==3, etc. just compare numbers to x.
You can have the possible numbers in an array and then compare it like:
int x = 1;
int[] compareArray = new[] { 1, 3, 12, 33 };
if (compareArray.Contains(x))
{
//condition met
}
Or you can use Enumerable.Any like:
if (compareArray.Any(r=> r == x))
You can do it fairly succinctly with a switch statement:
int x= 1;
switch (x)
{
case 1:
case 2:
case 3:
case 4:
Console.WriteLine("x is either 1, 2, 3, or 4");
break
default:
Console.WriteLine("x is not 1, 2, 3, or 4");
break;
}
Late to the party, and I would definitely, definitely suggest that one use a simple solution such as Habib's answer (and even simplifying it with extension methods). That said, I was curious if it were possible to achieve a minimal syntax along the lines of what Tagon may have been looking for. That is, would it be possible to have something like:
int x = 1;
if(x == 1 || 3 || 12 || 33)
{
}
I suspect there is unneeded verbosity with some of the operators I used here (and certainly some best-practices violations), but something like this is possible with operator overloads. The resulting syntax is:
IntComparer x = 1; //notice the usage of IntComparer instead of int
if(x == 1 || 3 || 12 || 33)
{
}
First I have a kind of "entry point" into the comparison:
public class IntComparer
{
public int Value { get; private set; }
public IntComparer(int value)
{
this.Value = value;
}
public static implicit operator IntComparer(int value)
{
return new IntComparer(value);
}
public static BoolComparer operator ==(IntComparer comparer, int value)
{
return new BoolComparer(comparer.Value, comparer.Value == value);
}
public static BoolComparer operator !=(IntComparer comparer, int value)
{
return new BoolComparer(comparer.Value, comparer.Value != value);
}
}
This satisfies the initial x == 1 check. From here on, it switches to a new type BoolComparer:
public class BoolComparer
{
public int Value { get; private set; }
public bool IsSatisfied { get; private set; }
public BoolComparer(int value, bool isSatisfied)
{
this.Value = value;
this.IsSatisfied = isSatisfied;
}
public static bool operator true(BoolComparer comparer)
{
return comparer.IsSatisfied;
}
public static bool operator false(BoolComparer comparer)
{
return !comparer.IsSatisfied;
}
public static implicit operator bool(BoolComparer comparer)
{
return comparer.IsSatisfied;
}
public static BoolComparer operator |(BoolComparer comparer, BoolComparer value)
{
return new BoolComparer(comparer.Value, comparer.Value == value.Value);
}
public static implicit operator BoolComparer(int value)
{
return new BoolComparer(value, false);
}
}
This satisfies the subsequent || 3 || 12 || 33 checks and the final true/false evaluation for the if statement.
These two classes working in conjunction makes the syntax tomfoolery work. It's terrible. Do not use it. Also, it doesn't work for for the negative: if (x != 1 || 3 || 12 || 33). That might be a simple fix, but I don't want to dive into that at the moment)
Some working checks:
IntComparer x = 1;
bool check1 = x == 1 || 3 || 12 || 33; //true
bool check2 = x == 2 || 3 || 12 || 33; //false
bool check3 = x == 5 || 1 || Int32.MaxValue; //true
bool check4 = x == -1; //false
Related
I want an alphabetic sort with one exception.
There is a Group with a Name = "Public" and an ID = "0" that I want first.
(would rather use ID = 0)
After that then sort the rest by Name.
This does not return public first.
public IEnumerable<GroupAuthority> GroupAuthoritysSorted
{
get
{
return GroupAuthoritys.OrderBy(x => x.Group.Name);
}
}
What I want is:
return GroupAuthoritys.Where(x => x.ID == 0)
UNION
GroupAuthoritys.Where(x => x.ID > 0).OrderBy(x => x.Group.Name);
GroupAuthority has a public property Group and Group has Public properties ID and Name.
I used basically the accepted answer
using System.ComponentModel;
namespace SortCustom
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
TestSort();
}
private void TestSort()
{
List<CustomSort> LCS = new List<CustomSort>();
LCS.Add(new CustomSort(5, "sss"));
LCS.Add(new CustomSort(6, "xxx"));
LCS.Add(new CustomSort(4, "xxx"));
LCS.Add(new CustomSort(3, "aaa"));
LCS.Add(new CustomSort(7, "bbb"));
LCS.Add(new CustomSort(0, "pub"));
LCS.Add(new CustomSort(2, "eee"));
LCS.Add(new CustomSort(3, "www"));
foreach (CustomSort cs in LCS) System.Diagnostics.Debug.WriteLine(cs.Name);
LCS.Sort();
foreach (CustomSort cs in LCS) System.Diagnostics.Debug.WriteLine(cs.Name);
}
}
public class CustomSort : Object, INotifyPropertyChanged, IComparable<CustomSort>
{
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(PropertyChangedEventArgs e)
{
if (PropertyChanged != null) PropertyChanged(this, e);
}
private Int16 id;
private string name;
public Int16 ID { get { return id; } }
public String Name { get { return name; } }
public int CompareTo(CustomSort obj)
{
if (this.ID == 0) return -1;
if (obj == null) return 1;
if (obj is CustomSort)
{
CustomSort comp = (CustomSort)obj;
if (comp.ID == 0) return 1;
return string.Compare(this.Name, comp.Name, true);
}
else
{
return 1;
}
}
public override bool Equals(Object obj)
{
// Check for null values and compare run-time types.
if (obj == null) return false;
if (!(obj is CustomSort)) return false;
CustomSort comp = (CustomSort)obj;
return (comp.ID == this.ID);
}
public override int GetHashCode()
{
return (Int32)ID;
}
public CustomSort(Int16 ID, String Name)
{
id = ID;
name = Name;
}
}
}
You need to use a comparison function, they are functions that from two instances of your type return an integer that return 0 if both are equals, a negative value if the first is less than the second and a positive value if the first is greater than the second.
MSDN has a nice table that is easier to follow than text (StackOverflow still doesn't support tables in 2014)
IComparer<T>
Most sort methods accept a custom comparer implementation of type IComparer<T> you should create one encapsulating your custom rules for Group :
class GroupComparer : IComparer<Group>
{
public int Compare(Group a, Group b)
{
if (a != null && b != null && (a.Id == 0 || b.Id == 0))
{
if (a.Id == b.Id)
{
// Mandatory as some sort algorithms require Compare(a, b) and Compare(b, a) to be consistent
return 0;
}
return a.Id == 0 ? -1 : 1;
}
if (a == null || b == null)
{
if (ReferenceEquals(a, b))
{
return 0;
}
return a == null ? -1 : 1;
}
return Comparer<string>.Default.Compare(a.Name, b.Name);
}
}
Usage:
items.OrderBy(_ => _, new GroupAuthorityComparer());
IComparable<T>
If it is the only way to compare Group instances you should make it implement IComparable<T> so that no aditional code is needed if anyone want to sort your class :
class Group : IComparable<Group>
{
...
public int CompareTo(Group b)
{
if (b != null && (Id == 0 || b.Id == 0))
{
if (Id == b.Id)
{
// Mandatory as some sort algorithms require Compare(a, b) and Compare(b, a) to be consistent
return 0;
}
return Id == 0 ? -1 : 1;
}
return Comparer<string>.Default.Compare(Name, b.Name);
}
}
Usage:
items.OrderBy(_ => _.Group);
The choice between one way or the other should be done depending on where this specific comparer is used: Is it the main ordering for this type of item or just the ordering that should be used in one specific case, for example only in some administrative view.
You can even go one level up and provide an IComparable<GroupAuthority> implementation (It's easy once Group implement IComparable<Group>):
class GroupAuthority : IComparable<GroupAuthority>
{
...
public int CompareTo(GroupAuthority b)
{
return Comparer<Group>.Default.Compare(Group, b.Group);
}
}
Usage:
items.OrderBy(_ => _);
The advantage of the last one is that it will be used automatically, so code like: GroupAuthoritys.ToList().Sort() will do the correct thing out of the box.
You can try something like this
list.Sort((x, y) =>
{
if (x.Id == 0)
{
return -1;
}
if (y.Id == 0)
{
return 1;
}
return x.Group.Name.CompareTo(y.Group.Name);
});
Where list is List<T>.
This method takes advantage of custom sort option provided by List<T> using Comparison<T> delegate.
Basically what this method does is, it just adds special condition for comparison when Id, If it is zero it will return a value indicating the object is smaller which makes the object to come in top of the list. If not, it sorts the object using its Group.Name property in ascending order.
public IEnumerable<GroupAuthority> GroupAuthoritysSorted
{
get
{
return GroupAuthoritys.OrderBy(x => x.Group.ID == 0)
.ThenBy(x => x.Group.Name);
}
}
Suppose I have a list of multi-part questions and each question has a QuestionNumber like 1, 1a,1b,2,2a and so on. I want to fetch a list of questions from the database using linq-to-entities, but ordered by QuestionNumber. The problem is that rather than using the correct order, it will use lexicographic ordering like
1
11
11a
11b
1a
1b
2
22
What I have so far is a custom comparer:
public class QuestionCompare : IComparer<Question>
{
public int Compare(Question x, Question y)
{
string a = x.QuestionNumber;
string b = y.QuestionNumber;
if (a == b)
{
return 0;
}
int aInt;
bool aBool = Int32.TryParse(new String(a.Where(Char.IsDigit).ToArray()), out aInt);
int bInt;
bool bBool = Int32.TryParse(new String(b.Where(Char.IsDigit).ToArray()), out bInt);
if (aBool)
{
if (bBool)
{
if (aInt > bInt)
{
return 1;
}
else if (aInt < bInt)
{
return -1;
}
else
{
string aLetter = new String(a.Where(Char.IsLetter).ToArray());
string bLetter = new String(a.Where(Char.IsLetter).ToArray());
return StringComparer.CurrentCulture.Compare(aLetter, bLetter);
}
}
else
{
return 1;
}
}
else
{
if (bBool)
{
return -1;
}
else
{
return StringComparer.CurrentCulture.Compare(a, b);
}
}
return 0;
}
}
And you can call Array.Sort(questionArray,new QuestionCompare()) to put the questions in the correct order.
However, I feel like this is a common and well defined order so I'm wondering if there are better implementations, perhaps even something built in to the .Net framework.
This comparer works fine and is a fair bit shorter.
public class QuestionCompare : IComparer<Question>
{
public int Compare(Question x, Question y)
{
string a = x.QuestionNumber;
string b = y.QuestionNumber;
var aDigits = new string(a.TakeWhile(c => char.IsDigit(c)).ToArray());
var bDigits = new string(b.TakeWhile(c => char.IsDigit(c)).ToArray());
int aInt = String.IsNullOrEmpty(aDigits) ? 0 : int.Parse(aDigits);
int bInt = String.IsNullOrEmpty(bDigits) ? 0 : int.Parse(bDigits);
return aInt != bInt ? aInt.CompareTo(bInt) : a.CompareTo(b);
}
}
I want to have a number (let's say i) whose range is between 0 to 26 so that when the number is 26 and it is incremented by 1 (say i++) the value returns to 0 (i.e. the value is circular).
Is there such a thing in c#? What is it called? If not then how would I implement this in code (overloaded operators are accepted).
Make a property that limits the value:
private int _value;
public int Value {
get { return _value; }
set { _value = value % 27; }
}
Now when you increase the property the setter will limit the value.
Example:
Value = 25;
Value++; // Value is now 26
Value++; // Value is now 0
Value++; // Value is now 1
You can try this:
int result = number % 27;
Use modulus operator (%)
var x = 0;
x = (x+1) % 27;
if you want it to go 0,1,2,3, ..... 24,25,26, 0, 1, 2, 3, ...
use modulus 27
I don't know of any sort of 'boundaries' or rules, you can "set" for an int in the way you want. I'd suggest creating an if statement, or two, to control it. `
if( i <= 26 & i >= 0)
{ ..do something..}
else i = 0;
Something like this should accomplish what you ask:
class CircularInt
{
public int value;
public static CircularInt operator ++(CircularInt c)
{
if (c.value >= 26)
c.value = 0;
else
c.value++;
return c;
}
}
Then use it:
CircularInt cInt = new CircularInt();
cInt++;
Console.WriteLine(cInt.value);
Another option is to define your own immutable type.
public struct Value27
{
private readonly int val;
private readonly bool isDef;
private Value27(int value)
{
while (value < 0) value += 27;
val = value % 27;
isDef = true;
}
public static Value27 Make(int value)
{ return new Value27(value); }
public bool HasValue { get { return isDef; } }
public int Value { get { return val; } }
public static Value27 operator +(Value27 curValue)
{ return Make(curValue.Value + 1); }
public static Value27 operator -(Value27 curValue)
{ return Make(curValue.Value + 26); }
public static implicit operator Value27(int bValue)
{ return Make(bValue); }
public static implicit operator int (Value27 value)
{ return value.Value; }
}
I would like to have expression classes that compare two objects and pass the below test.
public abstract class ComparisonExpression
{
public bool Evaluate(IComparable left, object right)
{
if (left == null && right == null)
return true;
if (left == null || right == null)
return false;
return GetResult(left.CompareTo(right));
}
protected abstract bool GetResult(int comparisonResult);
}
public class AreEqualExpression : ComparisonExpression
{
protected override bool GetResult(int comparisonResult)
{
return comparisonResult == 0;
}
}
// TEST
const int i = 123;
const long l = 123L;
const string s = "123";
Assert.IsTrue(new AreEqualExpression().Evaluate(i, l));
Assert.IsFalse(new AreEqualExpression().Evaluate(i, s));
Assert.IsFalse(new AreEqualExpression().Evaluate(l, s));
It seems like IComparable implementation expects the given type matches the current type. I am having an exception like "Object must be of type Int32.".
I thought returning false if types are not equal. It prevents the exception but it brakes the behavior that i want.
Also I thought about a type conversion but this time string and int comparison will return true, which i do not want.
Any suggestions?
If you define this helper class
public static class NumericalHelper {
public static double AsDouble(this object value, out bool success) {
if (value is sbyte || value is byte || value is short || value is ushort || value is int || value is uint || value is long || value is decimal || value is ulong || value is float || value is double || value.GetType().IsEnum) {
success = true;
return Convert.ToDouble(value);
}
success = false;
return 0;
}
}
you can do the comparison like this:
public bool Evaluate(IComparable left, object right) {
if (left == null && right == null)
return true;
if (left == null || right == null)
return false;
bool isNumerical;
double leftValue = left.AsDouble(out isNumerical);
double rightValue = isNumerical ? right.AsDouble(out isNumerical) : 0;
if (isNumerical)
return GetResult(Comparer<Double>.Default.Compare(leftValue, rightValue));
else {
if (left.GetType() == right.GetType())
return GetResult(left.CompareTo(right));
else
return false;
}
But beware that equality is usully compared with the Equals method or with the IEquatable interface, which isn't considered at all in your example. Here is more information about implementing equality. This seems to be an issue to me this doesn't fit well in use current class design.
I got frustated with my other question. So i wrote up this example.
In C the below is true. See demo
int main()
{
printf("%d", 1 && 2);
return 0;
}
Output:
1
In C#. It is FALSE. WHY is this false?
Also i dont understand why i needed to create the bool operator in this example but not the one in my other question but no matter. Why is the below false? it makes no sense to me.
BTW the logic making the below false is described here
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
MyInt a=1, b=2;
bool res=a && b;
Console.WriteLine("result is {0}", res);
}
class MyInt
{
public int val;
public static bool operator true(MyInt t) { return t.val != 0; }
public static bool operator false(MyInt t) { return t.val == 0; }
public static MyInt operator &(MyInt l, MyInt r) { return l.val & r.val; }
public static MyInt operator |(MyInt l, MyInt r) { return l.val | r.val; }
public static implicit operator MyInt(int v) { return new MyInt() { val = v }; }
public static implicit operator bool(MyInt t) { return t.val != 0; }
}
}
}
In C there is no bool. Convention is that 0 is false and != 0 is true. if statement treated conditional expression result exactly that way.
In C++ bool was introduced. But it was compatible with old rules, 0 treated as false and false as 0, and there was implicit conversion between int and bool.
In C# it is not the same way: there is bool and int and they are not convertible to eachother. That is what C# Standard says. Period.
So when you tried to reimplement bool and int compatibility you made a mistake. You use && which is logical operator, but in C# you can't override it and only &, which is implemented as bitwise. 1 & 2 == 0 == false! here it is!
You even should not overload bitwise ones, to maintain compatibility you just have to leave operator true and false.
This code works as you expect:
class Programx
{
static void Main(string[] args)
{
MyInt a = 1, b = 2;
bool res = a && b;
Console.WriteLine("result is {0}", res);
}
class MyInt
{
public int val;
public static bool operator true(MyInt t)
{
return t.val != 0;
}
public static bool operator false(MyInt t)
{
return t.val == 0;
}
public static implicit operator MyInt(int v)
{
return new MyInt() { val = v };
}
public static implicit operator bool(MyInt t)
{
return t.val != 0;
}
}
}
result is True
Your implementations of operator& and operator| are wrong. These binary operators have bitwise meanings when applied to integral types, and when applied to either Boolean types or classes that have their own & and | operators, they have logical AND and OR semantics (being the non-short-circuiting cousins of && and ||). Correct implementations would look as follows:
operator &(MyInt l, MyInt r) {return l.val != 0 && r.val != 0);}
operator |(MyInt l, MyInt r) {return l.val != 0 || r.val != 0);}
I'll try and make this simple, since I think people are overcomplicating this.
var x = 1 & 2;
// behind the scenes: 0001 AND 0010 = 0000
Console.Write(x); // 0, as shown above
Integers can NOT be used as booleans in C#. The result of:
if (1 && 2) // compile error
var x = 1 && 2; // compile error
There is no point to asking why an Integer can not be used as a boolean in C#, it just can't. The type system does not allow it. If one were to implement their own Integer class, they could provide implicit conversions from their type to bool, but int does not do this. You also have to make a choice when overloading; do you want bitwise behaviour, or logical behaviour. You can not have both.
Some languages allow 0, "", [] as 'falsey' values. C# does not. Get over it, and use a bool if you're doing boolean logic. If all else fails, Convert.ToBoolean on an int will return true for all non-zero values.
public static MyInt operator &(MyInt l, MyInt r) { return l.val & r.val; }
If I read the linked article correctly, res = a && b will be "expanded" to:
MyInt.false(a) ? a : MyInt.&(a, b)
MyInt.false(a) is false, so evaluates to:
MyInt.&(a, b)
which "expands" to:
a.val & b.val
which is (1 & 2) == 0, and thus false.