Operator Overloading with C# Extension Methods

Operator Overloading with C# Extension Methods

This is not currently possible, because extension methods must be in static classes, and static classes can't have operator overloads. But the feature is being discussed for some future release of C#. Mads talked a bit more about implementing it in this video from 2017.

On why it isn't currently implemented, Mads Torgersen, C# Language PM says:

...for the Orcas release we decided to
take the cautious approach and add
only regular extension methods, as
opposed to extention properties,
events, operators, static methods, etc
etc. Regular extension methods were
what we needed for LINQ, and they had
a syntactically minimal design that
could not be easily mimicked for some
of the other member kinds.

We are becoming increasingly aware
that other kinds of extension members
could be useful, and so we will return
to this issue after Orcas. No
guarantees, though!

Further below in the same article:

I am sorry to report that we will not
be doing this in the next release. We
did take extension members very
seriously in our plans, and spent a
lot of effort trying to get them
right, but in the end we couldn't get
it smooth enough, and decided to give
way to other interesting features.

This is still on our radar for future
releases. What will help is if we get
a good amount of compelling scenarios
that can help drive the right design.

C# - Operator Overload Extensions

Three options:

  1. Subclass them, and write overloads for the subclass
  2. Use Microsoft's publicly available source code for the respective classes (or decompile them), and write your overloads. This is not maintainable in the long term, or necessarily easy, but it will work.
  3. Stick with your extension methods.
  4. Conversion operators between your class and a "clone" class as described below.

In the comments, the OP has specifically mentioned using System.Drawing.PointF. What I've done in the past, with sealed classes like this, is to develop a second similar class using the .NET source as described above. Let's call this second class MyCustomPointF. I can write operators for my new class. But what I'm also going to add is what's called an implicit conversion operator that helps the compiler to convert an instance of my class back to a System.Drawing.PointF instance when I need it (without calling an external conversion function). It's not perfect, but it's an option.

Is it possible define an extension operator method?

No, it is not possible to do from outside of the class. ++ operator should be defined inside class which is being incremented. You can either create your own class which will be convertible from string and will have ++ overload or you can forget about this idea and use regular methods.

Is it possible to do operator overloading with List T without inheriting from it?

you can not do operator overload outside the class. you can use container for operator overloading

you can run this code hereurl


using System;
using System.Collections;
using System.Collections.Generic;

public class Program
{
public static void Main()
{
Run();
}

public static void Run()
{
var ls = new List<int>(){
1,3,5,7,9,11
};
var ls2 = new List<int>(){
2,4,6,8,10
};

var lsContainer = new AdditionContainer<List<int>,int>(ls);
var ls2Container = new AdditionContainer<List<int>,int>(ls2);
var finalAnsower = lsContainer +ls2Container;
finalAnsower.List.ForEach(f=>Console.WriteLine(f) );

}

}

public class AdditionContainer<TList,T>

where TList:List<T>
{
public TList List;
public AdditionContainer(TList list )
{
List=list;
}

public static AdditionContainer<TList,T> operator +(AdditionContainer<TList,T> a, AdditionContainer<TList,T> b)
{
b.List.ForEach(l =>{
if(!a.List.Contains(l))
{
a.List.Add(l);
}
});
return a;
}
}

Overloading operators using extension methods

C# already "lifts" all operators onto nullable types.

If either operand is null, the operator will return null.

You don't need to (and cannot) do that.

Extension methods vs overloading

We should use extension methods if we are quite sure that the methods are the same for the all (including potential) interface implementation:

  public interface IFoo {
void Bar(int a);
}

public static class FooExtensions {
public static void Bar(this IFoo foo, int a, int b) {...}
public static void Bar(this IFoo foo, int a, int b, int c) {...}
}

We can implement different Bar(int a) methods

  public MyFoo : IFoo {
void Bar(int a) { /* MyFoo algorithm here */}
}

public MyOtherFoo : IFoo {
void Bar(int a) { /* some other - MyOtherFoo - algorithm here */}
}

But Bar(int a, b) as well as Bar(int a, b, c) are still be the same:

  new MyFoo().Bar(1, 2);      // FooExtensions.Bar(IFoo, int, int) called
new MyOtherFoo().Bar(1, 2); // FooExtensions.Bar(IFoo, int, int) called

If, say, Bar(int a, int b) can vary from implementation to implementation we have have to add it into interface:

  public interface IFoo {
void Bar(int a);
void Bar(int a, int b);
}

...

public MyFoo : IFoo {
void Bar(int a) { /* MyFoo algorithm here */}
void Bar(int a, int b) { /* MyFoo algorithm here */}
}

public MyOtherFoo : IFoo {
void Bar(int a) { /* some other - MyOtherFoo - algorithm here */}
void Bar(int a, int b) { /* some other - MyOtherFoo - algorithm here */}
}

If almost all interface implementations have the same algorithm it'll be boring to put the boiler plate code. However, in C# 8.0 we are going to have a good compromise - default method implmentation, e.g.

  public interface IFoo {
void Bar(int a);
void Bar(int a, int b) {
/* Default code here */
}
}

// uses default code for Bar(int a, int b)
public MyFoo : IFoo {
void Bar(int a) { /* MyFoo algorithm here */}
}

// uses its own code for Bar(int a, int b)
public MyOtherFoo : IFoo {
void Bar(int a) { /* some other - MyOtherFoo - algorithm here */}
void Bar(int a, int b) { /* some other - MyOtherFoo - algorithm here */}
}

Unity3D, how can I write an extension method for operators?

You can not use extension method to overload on operator. Perhaps you can add .LessThan.

C# create operator overload for concrete type of generic class or struct

You can write an extension method -- this is what the runtime does for e.g. Vector128<T>. This does mean you need a method rather than an operator however.

public static class CRangeExtensions
{
public static CRange<double> Multiply(this CRange<double> range, double factor)
{
return new CRange(range.LowerBound * factor, range.UpperBound * factor);
}

// Same for int...
}

If you're OK using preview features, you can make use of Generic math which defines the INumber<T> interface:

public readonly struct CRange<T> where T : INumber<T>
{
public T LowerValue { get; }
public T UpperValue { get; }

public CRange(T lower, T upper) => (LowerValue, UpperValue) = (lower, upper);

public static CRange<T> operator * (CRange<T> range, T factor)
{
return new CRange<T>(range.LowerValue * factor, range.UpperValue * factor);
}
}

SharpLab.

Overloading Extension Methods

You aren't overloading here as the extension methods are on different objects, ExcelPackage and ExcelWorksheet. Overloading extension methods is acceptable though.

Extending the and operator for System.Type

Like the others have said, C# doesn't support extension operators. If you need to do this then you can implement a custom type, something like:

public class MyType : Type
{
private Type internalType;

public MyType(Type t)
{
internalType = t;
}

public static Boolean operator >(MyType t1, Type t2)
{
//TODO once it compiles
return false;
}

public static Boolean operator <(MyType t1, Type t2)
{
//TODO once it compiles
return true;
}

public override Assembly Assembly
{
get { return internalType.Assembly; }
}

public override string AssemblyQualifiedName
{
get { return internalType.AssemblyQualifiedName; }
}

public override Type BaseType
{
get { return internalType.BaseType; }
}

public override string FullName
{
get { return internalType.FullName; }
}

public override Guid GUID
{
get { return internalType.GUID; }
}

protected override TypeAttributes GetAttributeFlagsImpl()
{
return internalType.Attributes;
}

protected override ConstructorInfo GetConstructorImpl(BindingFlags bindingAttr, Binder binder, CallingConventions callConvention, Type[] types, ParameterModifier[] modifiers)
{
return internalType.GetConstructor(bindingAttr, binder, callConvention, types, modifiers);
}

public override ConstructorInfo[] GetConstructors(BindingFlags bindingAttr)
{
return internalType.GetConstructors(bindingAttr);
}

public override Type GetElementType()
{
return GetElementType();
}

public override EventInfo GetEvent(string name, BindingFlags bindingAttr)
{
return internalType.GetEvent(name, bindingAttr);
}

public override EventInfo[] GetEvents(BindingFlags bindingAttr)
{
return internalType.GetEvents(bindingAttr);
}

public override FieldInfo GetField(string name, BindingFlags bindingAttr)
{
return internalType.GetField(name, bindingAttr);
}

public override FieldInfo[] GetFields(BindingFlags bindingAttr)
{
return internalType.GetFields(bindingAttr);
}

public override Type GetInterface(string name, bool ignoreCase)
{
return internalType.GetInterface(name, ignoreCase);
}

public override Type[] GetInterfaces()
{
return internalType.GetInterfaces();
}

public override MemberInfo[] GetMembers(BindingFlags bindingAttr)
{
return internalType.GetMembers(bindingAttr);
}

protected override MethodInfo GetMethodImpl(string name, BindingFlags bindingAttr, Binder binder, CallingConventions callConvention, Type[] types, ParameterModifier[] modifiers)
{
return internalType.GetMethod(name, bindingAttr, binder, callConvention, types, modifiers);
}

public override MethodInfo[] GetMethods(BindingFlags bindingAttr)
{
return internalType.GetMethods(bindingAttr);
}

public override Type GetNestedType(string name, BindingFlags bindingAttr)
{
return internalType.GetNestedType(name, bindingAttr);
}

public override Type[] GetNestedTypes(BindingFlags bindingAttr)
{
return internalType.GetNestedTypes(bindingAttr);
}

public override PropertyInfo[] GetProperties(BindingFlags bindingAttr)
{
return internalType.GetProperties(bindingAttr);
}

protected override PropertyInfo GetPropertyImpl(string name, BindingFlags bindingAttr, Binder binder, Type returnType, Type[] types, ParameterModifier[] modifiers)
{
return internalType.GetProperty(name, bindingAttr, binder, returnType, types, modifiers);
}

protected override bool HasElementTypeImpl()
{
return internalType.HasElementType;
}

public override object InvokeMember(string name, BindingFlags invokeAttr, Binder binder, object target, object[] args, ParameterModifier[] modifiers, System.Globalization.CultureInfo culture, string[] namedParameters)
{
return internalType.InvokeMember(name, invokeAttr, binder, target, args, modifiers, culture, namedParameters);
}

protected override bool IsArrayImpl()
{
return internalType.IsArray;
}

protected override bool IsByRefImpl()
{
return internalType.IsByRef;
}

protected override bool IsCOMObjectImpl()
{
return internalType.IsCOMObject;
}

protected override bool IsPointerImpl()
{
return internalType.IsPointer;
}

protected override bool IsPrimitiveImpl()
{
return internalType.IsPrimitive;
}

public override Module Module
{
get { return internalType.Module; }
}

public override string Namespace
{
get { return internalType.Namespace; }
}

public override Type UnderlyingSystemType
{
get { return internalType.UnderlyingSystemType; }
}

public override object[] GetCustomAttributes(Type attributeType, bool inherit)
{
return internalType.GetCustomAttributes(attributeType, inherit);
}

public override object[] GetCustomAttributes(bool inherit)
{
return internalType.GetCustomAttributes(inherit);
}

public override bool IsDefined(Type attributeType, bool inherit)
{
return internalType.IsDefined(attributeType, inherit);
}

public override string Name
{
get { return internalType.Name; }
}
}

Alternatively it would probably be easier to implement a custom DynamicObject (C# 4+) which can delegate the calls.



Related Topics



Leave a reply



Submit