c++ 20 concepts alternative in c# - c#

In c++ 20 we can use concepts which works like the where keyword in c# but I'm wondering how can i check T has some operator overloaded on it.
c++ Example:-
template <class T>
concept SupportPlusEqual = requires (T t) { t += t };
template <class T>
requires SupportPlusEqual <T>
void Add (T& lhs, T& rhs)
{
lhs += rhs;
}
In this code T must have += operator defined.
Is there any way to do the same in c#?

I think the closest equivalent is if you use .NET 7, interfaces can now specify operators with the new static abstract and virtual members feature. For example:
public interface IHasAdd<T> where T : IHasAdd<T>
{
static abstract T operator +(T a, T b);
}
To use it, make a type like this:
public class Foo : IHasAdd<Foo>
{
public Foo(int someValue)
{
SomeValue = someValue;
}
public int SomeValue { get; init; }
public static Foo operator +(Foo a, Foo b)
{
return new Foo(a.SomeValue + b.SomeValue);
}
}
An example method that can use the interface:
public T AddTogether<T>(T first, T second)
where T : IHasAdd<T>
{
return first + second;
}
Which means you can now do this:
var result = AddTogether(new Foo(1), new Foo(2));
//result.SomeValue == 3

You can only restrict generic types to interfaces, there is no way to require a specific operator to be implemented.
From .Net 7 there is the generic math feature that accomplishes something similar. This includes a bunch of interfaces, like IAdditionOperators<TSelf,TOther,TResult>, that can be used as a generic type restriction, and should also have associated operators defined to perform the corresponding operator.
Note that c++ templates and c# generic while superficially similar are implemented quite differently. While c++ resolves everything in compile time, c# includes the generic types in the CIL code, and is only converted to machine code when jitted.

Related

Implicit conversion fails when changing struct to sealed class

Struct/class in question:
public struct HttpMethod
{
public static readonly HttpMethod Get = new HttpMethod("GET");
public static readonly HttpMethod Post = new HttpMethod("POST");
public static readonly HttpMethod Put = new HttpMethod("PUT");
public static readonly HttpMethod Patch = new HttpMethod("PATCH");
public static readonly HttpMethod Delete = new HttpMethod("DELETE");
private string _name;
public HttpMethod(string name)
{
// validation of name
_name = name.ToUpper();
}
public static implicit operator string(HttpMethod method)
{
return method._name;
}
public static implicit operator HttpMethod(string method)
{
return new HttpMethod(method);
}
public static bool IsValidHttpMethod(string method)
{
// ...
}
public override bool Equals(object obj)
{
// ...
}
public override int GetHashCode()
{
return _name.GetHashCode();
}
public override string ToString()
{
return _name;
}
}
The following code triggers the issue:
public class HttpRoute
{
public string Prefix { get; }
public HttpMethod[] Methods { get; }
public HttpRoute(string pattern, params HttpMethod[] methods)
{
if (pattern == null) throw new ArgumentNullException(nameof(pattern));
Prefix = pattern;
Methods = methods ?? new HttpMethod[0];
}
public bool CanAccept(HttpListenerRequest request)
{
return Methods.Contains(request.HttpMethod) && request.Url.AbsolutePath.StartsWith(Prefix);
}
}
The compiler error is created by changing the HttpMethod struct into a sealed class. The error is reported for return Methods.Contains(request.HttpMethod), note: request.HttpMethod in this case is a string. Which produces the following:
Error CS1929 'HttpMethod[]' does not contain a definition for 'Contains' and the best extension method overload 'Queryable.Contains<string>(IQueryable<string>, string)' requires a receiver of type 'IQueryable<string>'
My question is why? I can redesign the code to make it work, but I'm wanting to know why changing from struct to sealed class creates this weird error.
Edit: Adding a simplified set of example code (available here: https://dotnetfiddle.net/IZ9OXg). Take note that commenting out the implicit operator to string on the second class allows the code to compile:
public static void Main()
{
HttpMethod1[] Methods1 = new HttpMethod1[10];
HttpMethod2[] Methods2 = new HttpMethod2[10];
var res1 = Methods1.Contains("blah"); //works
var res2 = Methods2.Contains("blah"); //doesn't work
}
public struct HttpMethod1
{
public static implicit operator HttpMethod1(string method)
{
return new HttpMethod1();
}
public static implicit operator string (HttpMethod1 method)
{
return "";
}
}
public class HttpMethod2
{
public static implicit operator HttpMethod2(string method)
{
return new HttpMethod2();
}
//Comment out this method and it works fine
public static implicit operator string (HttpMethod2 method)
{
return "";
}
}
Things I know:
Plainly the problem is in type inference.
In the first case, T is deduced to be HttpMethod1.
In the struct case, there is no conversion from HttpMethod1[] to IEnumerable<string> because covariance only works on reference types.
In the class case, there is no conversion from HttpMethod2[] to IEnumerable<string> because covariance only works on reference conversions, and this is a user-defined conversion.
Things I suspect but need to confirm:
Something about the slight difference between my last two points is confusing the type inference algorithm.
UPDATE:
It has nothing to do with covariant array conversions. The problem repros even without array conversions.
It does however have to do with covariant interface conversions.
It has nothing to do with strings. (Strings are often a bit weird because they have a hard-to-remember conversion to IEnumerable<char> that occasionally messes up type inference.)
Here's a program fragment that displays the problem; update your conversions to convert to C instead of string:
public interface IFoo<out T> {}
public class C {}
public class Program
{
public static bool Contains<T>(IFoo<T> items, T item)
{
System.Console.WriteLine(typeof(T));
return true;
}
public static void Main()
{
IFoo<HttpMethod1> m1 = null;
IFoo<HttpMethod2> m2 = null;
var res1 = Contains(m1, new C()); //works
var res2 = Contains(m2, new C()); //doesn't work
}
}
This looks like a possible bug in type inference, and if it is, it is my fault; many apologies if that is the case. Sadly I do not have time to look into it further today. You might want to open an issue on github and have someone who still does this for a living look into it. I would be fascinated to learn what the result was, and if it turns out to be a bug in either the design or the implementation of the inference algorithm.
Firstly, this is an observed behavioural difference between structs and classes. The fact that you have 'sealed' your class does not affect the outcome in this scenario.
Also we know the following statement will compile as expected for HttpMethod type declared as both a struct and class, thanks to the implicit operator.
string method = HttpMethods[0];
Dealing with Arrays introduces some lesser understood compiler nuances.
Covariance
When HttpMethod is a class (reference type), with an array such as HttpRoute.HttpMethods Array covariance (12.5 C# 5.0 Language Spec) comes into play that allows HttpMethod[x] to be treated as an object. Covariance will respect inbuilt implicit reference conversions (such as type inheritance or conversion to object) and it will respect explicit operators, but it will not respect or look for user defined implicit operators. (While a bit ambigous the actual spec doc lists specifically default implicit operators and explicit operators, it does not mention the user defined operators but seeing everything else is so highly specified you can infer that user defined operators are not supported.)
Basically Covariance takes precedence over many generic type evaluations. More on this in a moment.
Array covariance specifically does not extend to arrays of value-types. For example, no conversion exists that permits an int[] to be treated as an object[].
So when HttpMethod is a struct (value type), covariance is no longer an issue and the following generic extension from System.Linq namespace will apply:
public static bool Contains<TSource>(this IEnumerable<TSource> source, TSource value);
Because you have passed in a string comparator, the Contains statement will be evaluated as follows:
public static bool Contains<string>(this IEnumerable<string> source, string value);
When HttpMethod is a class (Reference Type), thanks to covariance, HttpMethod[] in it's current form comparable only with Object[] and thus IEnumerable, but not IEnumerable< T >, Why not? because the compiler needs to be able to determine the type to generate the generic implementation of IEnumerable< T > and to determine if it can perform an explicit cast from object to T.
Put another way, Compiler cannot determine if T can definetly be a String or not, so it doesn't find the match in the Linq extension methods that we were expecting.
So what can you do about it? (! Not this !)
The first common attempt might be to try using .Cast< string >() to cast the HttpMethod instances to strings for the comparison:
return HttpMethods.Cast<string>().Contains(request.Method) && request.Url.AbsolutePath.StartsWith(Prefix);
You will find that this does not work. Even though The parameter for Cast< T > is of type IEnumerable, not IEnumerable< T >. It is provided to allow you to use older collections that do not implement the generic version of IEnumerable with LINQ. Cast< T > is only designed to convert non-generic objects to their "true" type through the process of evaluating common origins for reference types or Un-Boxing for value types. If Boxing and Unboxing (C# Programming Guide) only applies to value types (structs) and since our HttpMethod type is a reference type (class) the only common origin between HttpMethod and String is Object. On HttpMethod there is no implicit, or even explicit operator that accepts Object and as it is not a value type there is no in built un-box operator that the compiler can use.
Note that this Cast<> will fail at runtime in this scenario when HttpMethod is a value type (class) the compiler will be happy to let it build.
Final Workaround
Instead of Cast< T > or relying on implicit conversions we will need to force the elements in the HttpMethods array to be explicitly cast to string (This will still use out implicit operator!) but Linq again makes this a trivial, but necessary task:
return HttpMethods.Select(c => (string)c).Contains(request.Method) && request.Url.AbsolutePath.StartsWith(Prefix);

Trouble Converting Lambda Expression to Delegate Because of "some return types"

I'm writing a Linked List program in C# because I want to test how I feel about the language and I'm running into some serious difficulty. I'm trying to implement a Map method that functions like a Haskell map function (code below for both). However, I'm getting the error messages:
main.cs(43,66): error CS0029: Cannot implicitly convert type `void' to `MainClass.LinkedList<U>'
main.cs(43,33): error CS1662: Cannot convert `lambda expression' to delegate type `System.Func<MainClass.LinkedList<U>>' because some of the return types in the block are not implicitly convertible to the delegate return type
The relevant code in question:
Ideal Haskell code:
map :: [a] -> (a -> b) -> [b]
map (x:[]) f = (f x) : []
map (x:xs) f = (f x) : (map xs f)
C# code:
public class LinkedList<T> where T: class
{
public T first;
public LinkedList<T> rest;
public LinkedList(T x) {this.first = x;}
public void Join(LinkedList<T> xs)
{
Do(this.rest, ()=>this.rest.Join(xs), ()=>Assign(ref this.rest, xs));
}
public LinkedList<U> Map<U>(Func<T, U> f) where U: class
{
return DoR(this.rest, ()=>new LinkedList<U>(f(this.first)).Join(this.rest.Map(f)), ()=>new LinkedList<U>(f(this.first)));
}
public static void Assign<T>(ref T a, T b)
{
a = b;
}
public static U DoR<T, U>(T x, Func<U> f, Func<U> g)
{
if (x!=null) {return f();}
else {return g();}
}
public static void Do<T>(T x, Action f, Action g)
{
if (x != null) {f();}
else {g();}
}
While Assign, DoR (short for Do and Return), and Do seem like they're "code smell", they're what I came up with for trying to not write
if (x != null) {f();}
else {g();}
type statements (I'm used to patternmatching). If anybody has any better ideas, I'd love to know them, but mostly I'm concerned with the highlighted problem.
Starting with your immediate problem: the basic issue here is that you're mixing and matching lambda expressions that have either void return type or an actual return type. This can be addressed by changing your Join() method so that it returns the list used to call Join():
public LinkedList<T> Join(LinkedList<T> xs)
{
Do(this.rest, () => this.rest.Join(xs), () => Assign(ref this.rest, xs));
return this;
}
An alternative way would be to have a statement body lambda in the Map<U>() method that saves the new list to a variable and then returns that. But that adds a lot more code than just changing the Join() method, so it seems less preferable.
That said, you seem to be abusing C# a bit here. Just as when writing code in a functional language, one should really make an effort to write real functional code, in the manner idiomatic to that language, so too should one make an effort when writing C# code to write real imperative code, in the manner idiomatic to C#.
Yes, C# has some functional-like features in it, but they don't generally have the same power as the features found in real functional languages, and they are intended to allow C# programmers to get the low-hanging fruit of functional styles of code without having to switch languages. One particular thing also to be aware of is that lambda expressions generate a lot more code than normal C# imperative code.
Sticking to more idiomatic C# code, the data structure you're implementing above can be written much more concisely, and in a manner that creates much more efficient code. That would look something like this:
class LinkedList<T>
{
public T first;
public LinkedList<T> rest;
public LinkedList(T x) { first = x; }
public void Join(LinkedList<T> xs)
{
if (rest != null) rest.Join(xs);
else rest = xs;
}
public LinkedList<U> Map<U>(Func<T, U> f) where U : class
{
LinkedList<U> result = new LinkedList<U>(f(first));
if (rest != null) result.Join(rest.Map(f));
return result;
}
}
(For what it's worth, I don't see the point of the generic type constraint on your Map<U>() method. Why restrict it like that?)
Now, all that said, it seems to me that if you do want a functional-style linked-list implementation in C#, it would make sense to make it an immutable list. I'm not familiar with Haskell, but from my limited use of functional languages generally, I have the impression that immutability is a common feature in functional language data types, if not enforced 100% (e.g. XSL). So if trying to reimplement functional language constructs in C#, why not follow that paradigm?
See, for example, Eric Lippert's answer in Efficient implementation of immutable (double) LinkedList. Or his excellent series of articles on immutability in C# (you can start here: Immutability in C# Part One: Kinds of Immutability), where you can get ideas for how to create various immutable collection types.
In browsing Stack Overflow for related posts, I found several that, while not directly applicable to your question, may still be of interest (I know I found them very interesting):
how can I create a truly immutable doubly linked list in C#?
Immutable or not immutable?
Doubly Linked List in a Purely Functional Programming Language
Why does the same algorithm work in Scala much slower than in C#? And how to make it faster?
Converting C# code to F# (if statement)
I like that last one mainly for the way that in both the presentation of the question itself and the replies (answers and comments) help illustrate well why it's so important to avoid trying to just transliterate from one language to another, and instead to really try to become familiar with the way a language is designed to be used, and how common data structures and algorithms are represented in a given language, idiomatically.
Addendum:
Inspired by Eric Lippert's rough draft of an immutable list type, I wrote a different version that includes the Join() method, as well as the ability to add elements at the front and end of the list:
abstract class ImmutableList<T> : IEnumerable<T>
{
public static readonly ImmutableList<T> Empty = new EmptyList();
public abstract IEnumerator<T> GetEnumerator();
public abstract ImmutableList<T> AddLast(T t);
public abstract ImmutableList<T> InsertFirst(T t);
public ImmutableList<T> Join(ImmutableList<T> tail)
{
return new List(this, tail);
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
class EmptyList : ImmutableList<T>
{
public override ImmutableList<T> AddLast(T t)
{
return new LeafList(t);
}
public override IEnumerator<T> GetEnumerator()
{
yield break;
}
public override ImmutableList<T> InsertFirst(T t)
{
return AddLast(t);
}
}
abstract class NonEmptyList : ImmutableList<T>
{
public override ImmutableList<T> AddLast(T t)
{
return new List(this, new LeafList(t));
}
public override ImmutableList<T> InsertFirst(T t)
{
return new List(new LeafList(t), this);
}
}
class LeafList : NonEmptyList
{
private readonly T _value;
public LeafList(T t)
{
_value = t;
}
public override IEnumerator<T> GetEnumerator()
{
yield return _value;
}
}
class List : NonEmptyList
{
private readonly ImmutableList<T> _head;
private readonly ImmutableList<T> _tail;
public List(ImmutableList<T> head, ImmutableList<T> tail)
{
_head = head;
_tail = tail;
}
public override IEnumerator<T> GetEnumerator()
{
return _head.Concat(_tail).GetEnumerator();
}
}
}
The public API is a little different from Eric's. You enumerate it to access the elements. The implementation is different as well; using a binary tree was how I enabled the Join() method.
Note that with the interface IEnumerable<T> implemented, one way to implement the Map<U>() method is to not do it at all and instead just use the built-in Enumerable.Select():
ImmutableList<T> list = ...; // whatever your list is
Func<T, U> map = ...; // whatever your projection is
IEnumerable<U> mapped = list.Select(map);
As long as the map function is relatively inexpensive, that would work fine. Any time mapped is enumerated, it will re-enumerate list, applying the map function. The mapped enumeration remains immutable, because it's based on the immutable list object.
There are probably other ways to do it (for that matter, I know of at least one other), but the above is what made the most sense to be conceptually.

C# Generic Method with generic parameter whose type is different than that of the one used on the class

I have a generic base to represent some kind of numbers. I need to override some implicit conversions to built-in types (like short, ushort, int, uint, etc...). One possible way is to override every possible type as seen in the code below:
public class MyBaseClass<T>
where T : struct, IComparable, IComparable<T>, IEquatable<T>
{
private T _value;
public MyBaseClass(T value)
{
_value = value;
}
// Implicit Conversions
static public implicit operator MyBaseClass<T>(Int16 value)
=> new MyBaseClass<T>((dynamic)value);
static public implicit operator MyBaseClass<T>(UInt16 value)
=> new MyBaseClass<T>((dynamic)value);
static public implicit operator MyBaseClass<T>(Int32 value)
=> new MyBaseClass<T>((dynamic)value);
// ... some more implicit conversions...
}
The question is: Instead of having to do for every possible option, is there a way to do it only once with something like the below:
static public implicit operator MyBaseClass<T>(U value) where U: struct
=> new MyBaseClass<T>((dynamic)value);
I tried with and without the part where T : struct but with no prevail.
Any idea?
PS: The above code is a .NET Core C# on Mac using Visual Studio Code.

C# operators as functions

Is there a way to use operators as functions without declaring them manually?
Func<bool, bool> not = x => !x;
Similar to (+)/(-) in Haskell. Would be handy in various LINQ scenarios involving conditional query construction. Maybe some C# (4.0+) trick I don't know about.
Edit: here is a sample to clarify what I mean:
int MyWhere(Func<bool, bool, bool> cond) {}
a usual call would be:
MyWhere((x,y) => x && y)
a cool call would be (assuming Haskell style):
MyWhere((&&))
No.
You can find the definitions (F12 in VS) for the operators you can overload, and there exists a
// struct Double
public static bool operator ==(double left, double right);
But there is no way to call Double.operator==(a, b).
The Framework does offer a a.Equals(b) for this particualr case, but there is no a.Add(b).
For documentary purposes: user-defined operator are functions, however the C# language explicitly prohibits explicit calls (don't know the rationale). E.g.:
public class X
{
public static X operator+(X a, X b)
{
return new X();
}
}
public class Program
{
public static void Main(string[] args)
{
var q = new X() + new X();
X.op_Addition(q,q); // error CS0571:
// `Program.X.operator +(Program.X, Program.X)': cannot explicitly
// call operator or accessor
}
}
If you were writing IL, you'd write this:
newobj instance void class X::'.ctor'()
newobj instance void class X::'.ctor'()
call class X class X::op_Addition(class X, class X)
stloc.0
If i understand what you are want to do right, you can use System.Reflection and Delegate.CreateDelegate to create a delegate to the operator method.
Of course i never testet it, but operator methods are methods so it should work.
This could also be automated ( To save time compared to the straight forward method ).
See:
http://msdn.microsoft.com/de-de/library/53cz7sc6.aspx

typedef equivalent for overloading in c#

I have a bunch of code that has lots integers with different meanings (I'd rather a general solution but for a specific example: day-of-the-month vs. month-of-the-year vs. year etc.). I want to be able to overload a class constructor based on these meanings.
For example
int a; // takes role A
int b; // takes role B
var A = new Foo(a); // should call one constructor
var B = new Foo(b); // should call another constructor
Now clearly that won't work but if I could define a type (not just an alias) that is an int in all but name like this:
typedef int TypeA; // stealing the C syntax
typedef int TypeB;
I could do the overloading I need and let the type system keep track of what things are what. In particular this would allow me to be sure that values are not mixed up, for example a value returned from a function as a year is not used as a day-of-the-month.
Is there any way short of class or struct wrappers to do this in c#?
It would be nice if the solution would also work for floats and doubles.
There is no direct typedef equivalent, but you can do the following:
using TypeA = int;
using TypeB = int;
However, this just aliases the type rather than creating a new strong type. Therefore, the compiler will still treat them as an int when resolving method calls.
A better solution might be to create simple wrapper classes that wraps int and provides implicit casting, such as:
struct TypeA
{
public TypeA(int value)
{
this.realValue = value;
}
private int realValue;
public static implicit operator int(TypeA value)
{
return this.realValue;
}
public static implicit operator TypeA(int value)
{
return new TypeA(value);
}
}
However, in most situations, an enum would be more appropriate.
This may be way off, but couldnt you use an enum for this? Enum base is int, but is typed, and you could define different constructors based on the type of enum passed.
If it's just for the constructor, couldn't you use something like this:
int dom = 5;
int doy = 100;
Foo b = Foo.NewFromDayoftheMonth(dom);
Foo c = Foo.NewFromDayoftheYear(doy);
where each method are static and create a new Foo object based on the parameters passed in.
This seems like a solution to me, where there isn't much else of one.
I would also create a struct around the value :
public struct TypeA
{
private int value;
public TypeA(int value)
{
this.value = value;
}
public static explicit operator int(TypeA a)
{
return a.value;
}
public static explicit operator TypeA(int value)
{
return new TypeA(value);
}
}
you can also declare operators to combine types and methods to provide a rich type around the int value.
A Year type can provde a IsLeap property, a day of month can be restraint to values between 1 and 31 and provide a special arithmetic.

Categories