C # - использовать несколько типов в качестве параметров без написания нескольких определений? - PullRequest
0 голосов
/ 24 октября 2018

У меня есть конструктор класса, и мне нужно передать ему параметры разных типов.Я знаю, что могу написать конструкторы с разными сигнатурами, но это немного болезненно.

Есть ли способ разрешить параметру быть одним из двух разных типов:

Что мне нужно сделать:

public Line(Coordinate p1, Coordinate p2)
    {}

public Line(Point3d p1, Point3d p2)
    {}

public Line(Point3d p1, Coordinate p2)
    {}

public Line(Coordinate p1, Point3d p2)
    {}

Есть ли способ написать один конструктор, который принимает два параметра как координату или Point3d без написания четырех разных конструкторов?

Ответы [ 5 ]

0 голосов
/ 24 октября 2018

Одно из предположений, которое дает большинство ответов здесь, заключается в том, что у вас есть возможность обновить классы Coordinate или Point3d, чтобы вы могли реализовать интерфейс или добавить базовый класс.Если предположить, что это не так, лучшим решением может быть реализация шаблона фасада, чтобы вы могли извлечь нужные вам части классов Coordinate или Point3d (или любой другой приемлемый тип) в единый упрощенный класс или интерфейс.

Это позволяет вам иметь одного конструктора со строго типизированными параметрами, которые содержат именно то, что вам нужно использовать в вашем классе, и ни одного дополнительного багажа, который поставляется с классом Coordinate или Point3d.

0 голосов
/ 24 октября 2018

Мы хотели бы иметь интерфейс, который может поддерживать как Coordinate, так и Point3d.Если есть функциональные возможности, которые оба совместно используют, то вы можете создать базовый класс (который также может быть абстрактным, если мы не хотим, чтобы он создавался)

public class Coordinate :IBasePoint
{
}

public class Point3d:IBasePoint
{
}

, а затем использовать его следующим образом

public class Line
{
  public Line(IBasePoint p1, IBasePoint p2){}
}

Если вы можете поделиться общими функциями, вы можете реализовать базовый класс

public abstract class BasePoint
{
  //shared logic
}

public class Coordinate:BasePoint
{
}

public class Point3d:BasePoint
{
}

, а затем использовать его следующим образом

public class Line
{
  public Line(BasePoint p1, BasePoint p2)
  {
  }
}
0 голосов
/ 24 октября 2018

У вас есть несколько вариантов при этом.Я бы предложил создать интерфейс, содержащий общие методы и атрибуты, или использовать бокс / распаковку для передачи параметров в виде объектов и приведения их к типу, который вам необходим.

Для метода интерфейса вам нужно определитьобщий интерфейс:

public interface ICoordinatePoint
{
    void SomeMethod();
    int someAttribute;
}

Затем, при определении ваших классов, реализуйте этот интерфейс

public class Coordinate : ICoordinatePoint
public class Point3d : ICoordinatePoint

В вашей функции просто передайте переменные как ICoordinatePoint s

public Line(ICoordinatePoint p1, ICoordinatePoint p2)
{
    // Some stuff
}

Если вы хотите использовать бокс / распаковку, вы можете просто определить p1 и p2 как объекты:

public Line(object _p1, object _p2)
{
    Coordinate p1 = (Coordinate)_p1;
    Point3d p2 = (Point3d)_p2;
    // Some stuff
}

Редактировать: если вы хотите убедиться, что ваши объекты не принадлежат к каким-либо другим типамВы можете проверить типы перед кастингом:

if (p1.GetType() != typeof(Coordinate) && p1.GetType() != typeof(Point3d)
    // Raise error or return
if (p2.GetType() != typeof(Coordinate) && p1.GetType() != typeof(Point3d)
    // Raise error or return
0 голосов
/ 24 октября 2018

Вы можете попробовать дополнительные параметры.Следующее позволит любую комбинацию переменных, включая все нули.Вам нужно будет проверить все эти комбинации в конструкторе.

public Line(Coordinate c1 = null, Coordinate c2 = null, Point3d p1 = null, Point3d p2 = null)
{}

Если вы пойдете по этому маршруту, вы можете создать линию, только если выполнены определенные условия.Для этого рассмотрим следующую схему проектирования.Сделайте конструктор закрытым и создайте статический метод для возврата новой строки, только если выполнены условия.

public class Line{
    private Line(Coordinate c1 = null, Coordinate c2 = null, Point3d p1 = null, Point3d p2 = null)
    {}

    public static Line CreateLine(Coordinate c1 = null, Coordinate c2 = null, Point3d p1 = null, Point3d p2 = null)
    {
        if (/* favorable condition*/)
            return new Line(c1, c2, p1, p2);
        return null;
    }
}

Если бы Coordinate и Point3d реализовали общий интерфейс, я бы также предложил использовать обобщенные значения

public class Line<T1, T2>
    where T1: ICommonInterface
    where T2: ICommonInterface
{
    public Line(T1 p1, T2 p2)
    {
    }
}
0 голосов
/ 24 октября 2018

Вы можете использовать интерфейс в качестве параметра для конструктора.Затем вам нужно будет предоставить класс, который реализует этот интерфейс в качестве параметра.

public interface IClassInterface
{}

Затем вам нужно внедрить этот интерфейс в свои классы.

public Class : IClassInterface
{}

И, наконец, вам нужноиспользуйте этот интерфейс в качестве параметра для конструктора.

public Line(IClassInterface p1, IClassInterface p2)
{}

Таким образом, ваш конструктор будет принимать только классы с указанным интерфейсом в качестве параметра.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...