It is necessary to write a function that performs some logical operation on two operands in accordance with the operation that is entered in the string. I tried to do as below, but it did not work out. Help me please.

private bool cmpStr<T>(string s, T c1, T c2) { if (s == ">") return c1 > c2; else if (s == ">=") return c1 >= c2; else if (s == "==") return c1 == c2; else if (s == "<=") return c1 <= c2; else if (s == "<") return c1 < c2; else return false; } 
  • possible duplicate of Disadvantages of generic types in C # - PashaPash
  • @PashaPash not. - andreycha
  • @andreycha the first line in the answer to Vlad - the inability to use +, (and put the constraint on it). But if between + and <such a huge difference - then ok - no :) - PashaPash
  • @PashaPash a person has a specific question. He was given three specific answers that explain the problem and suggest solutions. The original question would not help the author. - andreycha

3 answers 3

The fact is that with this declaration:

 cmpStr<T>(string s, T c1, T c2) 

arguments of any type can be passed to the method. In this case, all operations that are carried out in a method with arguments must be supported by the type of this argument. Does any type support operations <,>, <=,> =? No, not any. Therefore, this code is incorrect.

In order for the code to work, the type parameter Т needs to impose a restriction: for Т be of the type (or its subtype) that supports the operations you need. Alternatively, you can enter some type (for example, MyType ) in which these operations will be redefined. And then specify the limit:

 cmpStr<T>(string s, T c1, T c2) where T : MyType 

MyType can be a wrapper:

 public class MyType { public int Value; public static bool operator <(MyType a1, MyType a2) { return a1.Value < a2.Value; } public static bool operator >(MyType a1, MyType a2) { return a1.Value > a2.Value; } ... } 

(At the same time, we encounter a new problem: Value too, I want to make a generic, but it is impossible. A vicious circle.)

Also, MyType may not be a wrapper, but contain its own logic.


That is the general answer. Clarify your task, and I will clarify the answer.


PS Finally, a couple of links to alternative solutions: https://stackoverflow.com/a/18875731/1985167 http://www.yoda.arachsys.com/csharp/miscutil/usage/genericoperators.html

  • Thanks for the answer. As I understand it, it is much easier to rewrite this function twice :) - bitrixhater
  • @Nikita_Rabykin tell me what problem you solve. Why twice? - andreycha
  • I wanted to do something like this: pastebin.com/STKBa6Jq That is, compare 2 variables of simple type, using the string as an operator. - bitrixhater

Use the IComparable or IComparable<T> restriction - which allows you to use the Compare method, made specifically for such situations. You can also take IComparer<T> separate argument - then the restriction is not required.

Now you can rewrite your code like this:

 private bool cmpStr<T>(string s, T c1, T c2) where T : IComparable<T> { if (s == ">") return c1.Compare(c2) > 0; else if (s == ">=") return c1.Compare(c2) >= 0; else if (s == "==") return c1.Compare(c2) == 0; else if (s == "<=") return c1.Compare(c2) <= 0; else if (s == "<") return c1.Compare(c2) < 0; else return false; } private bool cmpStr<T>(string s, T c1, T c2, IComparer<T> comparer) { if (s == ">") return comparer.Compare(c1, c2) > 0; else if (s == ">=") return comparer.Compare(c1, c2) >= 0; else if (s == "==") return comparer.Compare(c1, c2) == 0; else if (s == "<=") return comparer.Compare(c1, c2) <= 0; else if (s == "<") return comparer.Compare(c1, c2) < 0; else return false; } 

The main advantage of this approach is that all ordered primitive types already implement this interface.

    I would do this by limiting the T type to the IComparable interface:

     private bool cmpStr<T>(string s, T c1, T c2) where T : IComparable<T> { int res = c1.CompareTo(c2); switch (s) { case ">": return res > 0; case ">=": return res >= 0; case "==": return res == 0; case "<=": return res <= 0; case "<": return res < 0; default: throw new ArgumentException(); } } 

    Numeric types support this interface.