Using implicit conversion as a replacement for multiple inheritance in .NET.

I have a situation where I would like objects of a certain type to be used as two different types. If one of the "base" types was an interface, that would not be a problem, but in my case it is preferable that both of them be concrete types.

I am considering adding copies of the methods and properties of one of the base types to a derived type and adding an implicit conversion from a derived type to this base type. Then users will be able to process the derived type as the base type using the duplicated methods directly, assigning it to a variable of the base type or passing it to a method that takes the base type.

It seems that this solution will satisfy my needs, but I did not miss anything? Is there a situation where this does not work, or where is it likely to add confusion instead of simplicity when using the API?

EDIT: More about my specific scenario:

This is a potential future redesign of how indicators are written in RightEdge , which is the development environment for an automated trading system. Price data are presented as a series of bars that are relevant for open, low, high and closed prices for a given period (1 minute, 1 day, etc.). Indicators perform calculations on a series of data. An example of a simple indicator is a moving average indicator, which gives a moving average of the last n values ​​of its input, where n is set by the user. A moving average can be applied to close the panel, or it can be applied to the output of another indicator to smooth it.

Each time a new bar appears, indicators calculate a new value for their output for this line.

, (. MACD) .

, "", , . , ( ), . , SMA.Current SMA, , SMA.Output.Current. , Indicator2.Input = Indicator1; Indicator2.Input = Indicator1.Output;. , .NET, .

- , .

+3
6

, , .

:
B D, :

B my_B_object = my_D_object;

. , B D , my_D_object ( , B ) my_B_object.

, "" ( , ), ( , , - " " ): .

, , ? + + ( # 3.0 .Net 3.5 ), . :

interface MyType { ... }
static class MyTypeHelper {
    public static void MyMethod(this MyType value) {...}
}

"" , .

; ; Helper:

  • System.Type value.GetType()
  • , ,
  • , ( Helper ).
  • , , " ".

: #, , , , - ; , .

, , ? , . , , ;)

, .


[EDIT: ]

. , , , ( NewBar), , , .

, . , - , + + , :

  • ( , ): ( "" , ), .
  • ( , ): , .
  • ( , , ): .
  • : ( , , ): , : d get, , . , ( ) , , , : P

. "" , , . , .

, ,

, ( ) .

(.. NewBar), ,

, ( , - ) . , . ( , ).

( ) , , (, , ). , . API, ?;) , . :

if(System.Reflection.Assembly.GetCallingAssembly()!=System.Reflection.Assembly.GetExecutingAssembly())
    throw new Exception("Don't call me. Don't call me!. DON'T CALL ME!!!");

, , using System.Reflection;. , BTW, - ;).

+4

:

  • , , - IntelliSense.

  • .

, , .

, :

class Person { }

abstract class Student : Person
{
    public abstract decimal Wage { get; }
}

abstract class Musician : Person
{
    public abstract decimal Wage { get; }
}

class StudentMusician : Person
{
    public decimal MusicianWage { get { return 10; } }

    public decimal StudentWage { get { return 8; } }

    public Musician AsMusician() { return new MusicianFacade(this); }

    public Student AsStudent() { return new StudentFacade(this); }
}

:

void PayMusician(Musician musician) { GiveMoney(musician, musician.Wage); }

void PayStudent(Student student) { GiveMoney(student, student.Wage); }

StudentMusician alice;
PayStudent(alice.AsStudent());
+1

, . .

++, :

class A {};
class B {};
class C : public A, public B {};

C o;
B* pB = &o;
A* pA = dynamic_cast<A*>(pB); // with true MI, this succeeds
+1

, , .

-. . , , new, . , -.

, , .

0

, , , Rx (Rx 15 ).

Rx - , . , .

, :

class Bar
{
    double Open { get; }
    double Low { get; }
    double High { get; }
    double Close { get; }
}

- , :

class Series : IObservable<Bar>
{
    // ...
}

- , , :

static class IndicatorExtensions
{
    public static IObservable<double> MovingAverage(
        this IObservable<Bar> source,
        int count)
    {
        // ...
    }
}

:

Series series = GetSeries();

series.MovingAverage(20).Subscribe(average =>
{
    txtCurrentAverage.Text = average.ToString();
});

GroupBy.

0

It might be a dumb idea, but: if your design requires multiple inheritance, then why don't you just use the language with MI? There are several .NET languages ​​that support multiple inheritance. From head to head: Eiffel, Python, Yok. Most likely.

0
source

Source: https://habr.com/ru/post/1741681/


All Articles