Abstract classes with operator overloading I'm following a YouTube video and am wondering if there are any other efficient ways of doing this. Is it possible to do it with an interface too?

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Learning
{
    class Program
    {
        static void Main(string[] args)
        {
            Shape Rect = new Rectangle(5, 3);
            Shape Tri = new Triangle(8, 12);
            Rectangle CombinedRectangle = new Rectangle(3, 3) + new Rectangle(6, 6);
            Console.WriteLine(CombinedRectangle.Area());
        }



        abstract class Shape
        {
             public abstract double Area();

        }

        class Triangle : Shape
        {
            private double theBase { get; set; }
            private double theHeight { get; set; }

            public Triangle(double theBase, double theHeight)
            {
                this.theBase = theBase;
                this.theHeight = theHeight;
            }

            public override double Area()
            {
                return (theBase * theHeight) / 2;
            }
        }

        class Rectangle : Shape
        {
            private double Length { get; set; }
            private double Width { get; set; }

            public Rectangle(double Length, double Width)
            {
                this.Length = Length;
                this.Width = Width;
            }

            public override double Area()
            {
                return Length * Width;
            }

            public static Rectangle operator+ (Rectangle r1, Rectangle r2)
            {
                double combinedWidth = r1.Width + r2.Width;
                double combinedLength = r1.Length + r2.Length;
                return new Rectangle(combinedLength, combinedWidth);
            }
        }

    }
}
To answer your direct question, yes an interface would be better than an abstract class.  Plus you may want to consider that Area could be a property rather than a method.

To address things you didn't ask about:

For the Triangle class, you may want to give simpler names to the base and height.  So Base instead of theBase and Height instead of theHeight.  And they should be public properties, perhaps with private setters.

public double Base { get; private set; }
public double Height { get; private set; }


For Rectangle class, the Length and Width could also be public.

public double Length { get; private set; }
public double Width { get; private set; }


Also the constructor should use lower casing for the arguments:

public Rectangle(double length, double width)


The operator could be shortened:

public static Rectangle operator+ (Rectangle r1, Rectangle r2)
{
    return new Rectangle(r1.Length + r2.Length, r2.Width+ r2.Width);
}


Or if you are using C# 6.0:

public static Rectangle operator+ (Rectangle r1, Rectangle r2) =&gt; new Rectangle(r1.Length + r2.Length, r2.Width+ r2.Width);


The last line uses an Expression-bodied function member found in C# 6.0.  A single line method body can be replaced with a 'lambda arrow' and you can omit the return since its implied.

Putting it altogether

Using C# version 6.0 syntax

interface IShape
{
    double Area { get; }
}

public class Triangle: IShape
{
    public double Base { get; private set; }
    public double Height { get; private set; }
    public Triangle(double theBase, double theHeight)
    {
        Base = theBase;
        Height = theHeight;
    }
    public double Area =&gt; (Base * Height) / 2;
}

public class Rectangle : IShape
{
    public double Length { get; private set; }
    public double Width { get; private set; }
    public Rectangle(double length, double width)
    {
        Length = length;
        Width = width;
    }
    public double Area =&gt; Length * Width;

    public static Rectangle operator+(Rectangle r1, Rectangle r2) =&gt; new Rectangle(r1.Length + r2.Length, r2.Width+ r2.Width);
}