Это допустимый способ иметь C# классы совместно использовать объекты? - PullRequest
0 голосов
/ 31 марта 2020

У меня есть набор классов, которые будут сериализованы в xml файлы. Классы делятся некоторыми данными. Я смотрел на некоторые подобные вопросы, но ни один из них, кажется, не делает это так, как я хотел бы. В основном подход, который кажется мне лучшим, заключается в создании базового класса, который содержит объект, в котором хранятся данные. Затем я могу передать данные, инкапсулированные в объект, в производные классы через этот объект. Таким образом, мне не нужно определять поля в классах, чтобы делиться ссылкой на этот общий объект. Я написал упрощенный пример этого подхода, и он, кажется, работает так, как я ожидал.

Мой вопрос - это лучший способ добиться этого? Есть ли лучший способ?

Спасибо!

пример:

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

namespace test
{
    public class SharedProperties
    {
        public int x = 0;
    }

    public class BaseA
    {
        private SharedProperties s;

        protected BaseA(SharedProperties sparm)
        {
            s = sparm;
        }

        public int spx { get => s.x ; set => s.x = value; }
    }

    public class Derived1 : BaseA
    {
        public Derived1() : base(null) { }

        public Derived1(SharedProperties x) : base(x) { }

    }

    public class Derived2 : BaseA
    {
        public Derived2() : base(null) { }

        public Derived2(SharedProperties x) : base(x) { }

    }

    internal class Program
    {
        private static void Main(string[] args)
        {
            SharedProperties sp = new SharedProperties();

            Derived1 d1 = new Derived1(sp);

            Derived2 d2 = new Derived2(sp);

            d1.spx = 1;

            Console.WriteLine("d2.spx = {0}", d2.spx);

            d2.spx = 2;

            Console.WriteLine("d1.spx = {0}", d1.spx);

        }
    }
}

Ответы [ 2 ]

3 голосов
/ 31 марта 2020

Zen из Python говорит, что

Явное лучше, чем неявное

Даже если это не Python, это правило также работает и здесь. Когда вы передаете один и тот же параметр SharedProperties, не очевидно, что изменение spx в любом из классов повлияет на другие классы. Это отладочный кошмар и очень трудно читать и поддерживать. Если вам нужны общие свойства, создайте отдельный класс / сервис, внедрите его в свои экземпляры и измените параметры, используя его, вместо того, чтобы изменять его неявным образом, используя свойство spx.

0 голосов
/ 31 марта 2020

Извините, немного изменил ваш код, чтобы сделать его не таким абстрактным.

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

public class Program
{
    public class Color
    {
        public string Name { get; set; } = "blue";
    }

    public abstract class Cup
    {
        protected Color Color { get; private set; }
        protected Cup(Color color)
        {
            Color = color;
        }

        public string ColorName 
        { 
            get => Color.Name; 

            /// ATTENTION:
            /// Try to avoid setting properties of shared properties
            /// this will lead to errors and is very difficult to 
            /// find in debugging or searching for potential errors
            set => Color.Name = value; 
        }
    }

    public class TeaCup : Cup
    {
        public TeaCup() : base(null) { }
        public TeaCup(Color color) : base(color) { }
    }

    public class CoffeeCup : Cup
    {
        public CoffeeCup() : base(null) { }
        public CoffeeCup(Color color) : base(color) { }
    }

    private static void Main(string[] args)
    {
        var color = new Color();
        var cup1 = new TeaCup(color);
        var cup2 = new CoffeeCup(color);

        Console.WriteLine("color = {0}", color.Name);

        cup1.ColorName = "red";
        Console.WriteLine("cup1.ColorName = {0}", cup1.ColorName);
        Console.WriteLine("cup2.ColorName = {0}", cup2.ColorName);

        cup2.ColorName = "green";
        Console.WriteLine("cup1.ColorName = {0}", cup1.ColorName);
        Console.WriteLine("cup2.ColorName = {0}", cup2.ColorName);
    }
}

Если вы сейчас измените Color.Name, он будет изменен в каждой Cup реализации, которая была создана с тем же color. См. Комментарий в коде.

Я думаю, что лучше явно установить Color.Name непосредственно для экземпляра Color, не передаваемого другим экземпляром упаковки (Cup).

Первый подход: ссылка .netfiddle, чтобы попробовать это

Так что, по моему мнению, лучший подход - внедрить нечто вроде поставщика / службы SharedProperties (Color)

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

public class Program
{
    public interface IColorProvider
    {
        string GetName();
    }

    public class ColorProvider : IColorProvider
    {
        private string _name = "blue";
        public void SetName(string name) { _name = name; }
        public string GetName() { return _name; }
    }

    public abstract class Cup
    {
        private readonly IColorProvider _colorProvider;
        protected Cup(IColorProvider colorProvider)
        {
            _colorProvider = colorProvider;
        }

        public string ColorName { 
            get => _colorProvider.GetName(); 
        }
    }

    public class TeaCup : Cup
    {
        public TeaCup() : base(null) { }
        public TeaCup(IColorProvider colorProvider) : base(colorProvider) { }
    }

    public class CoffeeCup : Cup
    {
        public CoffeeCup() : base(null) { }
        public CoffeeCup(IColorProvider colorProvider) : base(colorProvider) { }
    }

    private static void Main(string[] args)
    {
        var colorProvider = new ColorProvider();
        var cup1 = new TeaCup(colorProvider);
        var cup2 = new CoffeeCup(colorProvider);

        Console.WriteLine("color = {0}", colorProvider.GetName());

        colorProvider.SetName( "red");
        Console.WriteLine("cup1.ColorName = {0}", cup1.ColorName);
        Console.WriteLine("cup2.ColorName = {0}", cup2.ColorName);

        colorProvider.SetName( "green");
        Console.WriteLine("cup1.ColorName = {0}", cup1.ColorName);
        Console.WriteLine("cup2.ColorName = {0}", cup2.ColorName);
    }
}

Второй подход: ссылка .netfiddle для проверки

...