Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Some code for generic operators implementation #729

Closed
ebfortin opened this issue Dec 26, 2019 · 2 comments
Closed

Some code for generic operators implementation #729

ebfortin opened this issue Dec 26, 2019 · 2 comments

Comments

@ebfortin
Copy link
Contributor

ebfortin commented Dec 26, 2019

Here's some code I'm using on another library I'm working on. It allows for arithmetic operations on generic types. Very useful for having operators applied to generic type. It doesn't allow the use of the actual operator, but it allows to avoid the "operator + not defined for generic type T" error. And it provides more performance than having the need to implement an IOperators interface.

Only drawback : depending on the type T used to instantiate the generic class, you may get a RuntimeError instead of catching it at compile time. I think it's still worth it.

`

    public class Operators<T>
{
	public static Func<T, T, T> Add = GenerateAdditionExpression();
	public static Func<T, T, T> Sub = GenerateSubtractExpression();
	public static Func<T, T, T> Mul = GenerateMultiplyExpression();
	public static Func<T, T, T> Div = GenerateDivideExpression();


	private static Func<T, T, T> GenerateAdditionExpression()
	{
		var l = Expression.Parameter(typeof(T));
		var r = Expression.Parameter(typeof(T));
		var add = Expression.Add(l, r);
		return Expression.Lambda<Func<T, T, T>>(add, l, r).Compile();
	}

	private static Func<T, T, T> GenerateSubtractExpression()
	{
		var l = Expression.Parameter(typeof(T));
		var r = Expression.Parameter(typeof(T));
		var add = Expression.Subtract(l, r);
		return Expression.Lambda<Func<T, T, T>>(add, l, r).Compile();
	}

	private static Func<T, T, T> GenerateMultiplyExpression()
	{
		var l = Expression.Parameter(typeof(T));
		var r = Expression.Parameter(typeof(T));
		var add = Expression.Multiply(l, r);
		return Expression.Lambda<Func<T, T, T>>(add, l, r).Compile();
	}

	private static Func<T, T, T> GenerateDivideExpression()
	{
		var l = Expression.Parameter(typeof(T));
		var r = Expression.Parameter(typeof(T));
		var add = Expression.Divide(l, r);
		return Expression.Lambda<Func<T, T, T>>(add, l, r).Compile();
	}

}

`

I also have a class for casting. Same drawback as for aithmetics ones : you'll get the error at runtime, not compile time, if the type can't be casted to the specified one.

`

public class CastOperators<T, U>
{
	public static Func<T, U> Cast = GenerateCastExpression();

	private static Func<T, U> GenerateCastExpression()
	{
		var l = Expression.Parameter(typeof(T));
		var cast = Expression.Convert(l, typeof(U));
		return Expression.Lambda<Func<T, U>>(cast, l).Compile();
	}

}

`

@ebfortin
Copy link
Contributor Author

I just realized that someone already proposed something similar, with a even better structure.

@angularsen
Copy link
Owner

Thanks for posting. As you mention, we have discussed something similar before in #666 and #695, using runtime compilation to allow for performant arithmetic with different numeric types.

There is a PR on this here: #698

Closing this in favor of continuing discussions in those.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants