CommunityToolkit / dotnet

.NET Community Toolkit is a collection of helpers and APIs that work for all .NET developers and are agnostic of any specific UI platform. The toolkit is maintained and published by Microsoft, and part of the .NET Foundation.
https://docs.microsoft.com/dotnet/communitytoolkit/?WT.mc_id=dotnet-0000-bramin
Other
2.99k stars 294 forks source link

Multiple Inheritance Compiler Error CS1721 #618

Closed SkyGen closed 1 year ago

SkyGen commented 1 year ago

Describe the bug

Hi!

I would like to use ObservableObject for MVVM projects but I would need to inherit from multiple classes (see error in screenshot). My projects must inherit from DockPane, as it is a required class for the company I work for.

I noticed in the doc for error CS1721, it mentions a class may only inherit directly from a single class; however, a class can implement any number of interfaces. Is there a chance you might add an IObservableObject interface to CommunityToolkit.Mvvm?

Thanks! -Denny

Regression

No response

Steps to reproduce

Allow multiple inheritance via interface. See Expected Behavior example.

Expected behavior

partial class OutputDockPane : DockPane, IObservableObject { }

Screenshots

ObservableObject Multiple Inheritance

IDE and version

VS 2022

IDE version

17.5.0

Nuget packages

Nuget package version(s)

8.1.0

Additional context

No response

Help us help you

No, just wanted to report this

TruePluto commented 1 year ago

I don't think It is a good idea to make a DockPanel as a ObservableObject because it is a class of view, ObservableObject is used as a ViewModel but if you insist you can try the following code

[ObservableObject]
partial class OutputDockPane : DockPane
{
}
SkyGen commented 1 year ago

Thanks @TruePluto

Sergio0694 commented 1 year ago

This is by design. As mentioned, C# doesn't support multiple inheritance. For situations like these though, you can work around it and get the same functionality by using [ObservableObject], that's exactly what it's made for 🙂 My suggestion would be to have a base type like this:

[ObservableObject]
public abstract partial class ObservableDockPane : DockPane
{
}

And then just always inherit from this one for your types. This will give you the same features but it will greatly reduce binary size compared to just always using [ObservableObject] in each of your types (as this way the code will be shared).

SkyGen commented 1 year ago

Much thanks, @Sergio0694. Unfortunatley I can't use the attribute decoration either because one of the DockPane base classes implements INotifyPropertyChanged. I really like the idea of simplified code, though, and I'll keep ObserableObject in mind for other projects. I like your implementation better than that in DockPane - I may try to convince some around here with some changes, thanks! Keep up the great work!