2016-08-29 15 views
5

Czy istnieje sposób na połączenie tych dwóch konstruktorów w jeden? Zasadniczo akceptują tę samą tablicę typu Point3D.Scalanie par i IList <T> konstruktorzy

public Curve(int degree, params Point3D[] points) {} 

public Curve(int degree, IList<Point3D> points) {} 

Dzięki.

+1

Wymień pierwszy telefon na drugi. –

+1

Nie można ich scalić, jeśli chcesz obsługiwać funkcję 'params' (używając pojedynczych wartości). Każdy 'Point3D []' jest 'IList ' ale nie każdy 'IList ' jest tablicą. Tak więc możesz pozwolić konstruktorowi 'params' wywołać konstruktor' IList': 'ten (stopień, (IList ) punkty)' –

Odpowiedz

0

Jeśli mam zrozumienia zostanie poprawnie, problem jest, że nie można po prostu wykonaj następujące czynności:

public Curve(int degree, params Point3D[] points) 
      : this(degree, points) //want to chain to (int, IList<Point3D>) constructor 
{ 
} 

public Curve(int degree, IList<Point3D> points) 
{ 
} 

Ponieważ pojawia się następujący błąd czasu kompilacji: Error CS0516 Constructor 'Curve.Curve(int, params int[])' cannot call itself".

Można to obejść przez proste odlewanie odniesienia do typu jest właściwa

public Curve(int degree, params Point3D[] points) 
    : this(degree, (IList<Point3D>)points) 
{ 
} 

ten działa, ponieważ i tablicy T[] realizuje IList<T>.

+0

@CSharpie Nie, nie, to dokładnie taki punkt odpowiedzi; łańcuchowanie bezpośrednio nie zadziała z powodu 'CS0516' (konstruktora wywołującego się). Wyraźna obsada służy do uniknięcia tego problemu. Przed spadkiem przynajmniej mieć przyzwoitość, by przeczytać kompletną odpowiedź. – InBetween

+0

To jest lato. Nie mogę usunąć downvote, chyba że edytujesz tę odpowiedź. Nie wiem, o czym myślałem. – CSharpie

+0

Nieco mylić, jak ta odpowiedź różni się i dodaje poprzednie odpowiedzi, które wyjaśniły to samo ... –

4

Jeśli chcesz mieć 2 różne konstruktorów można:

public Curve(int degree, params Point3D[] points) : this(degree, (IList<Point3D>)points) { } 
public Curve(int degree, IList<Point3D> points) { } 

Albo jeśli chcesz tylko jeden konstruktor powiedzmy, że pierwsza to można zainicjować tak:

new Curve(0,new List<Point3D>().ToArray()); 

Poprzez jedną konstruktor wywołujący drugą nie musi duplikować całej logiki i nadal włączy oba formaty inicjowania.


Choć Array realizuje IList<T> nie można usunąć (IList<Point3D) powodu skompilować błędu: compiler ...... cannot call itself

enter image description here

+2

Zrób to na odwrót. To wymaga tylko rzutowania zamiast kopiowania całej kolekcji. –

+0

@Dennis_E - poprawiony :) –

+0

@CSharpie - zgadzam się, że Array implementuje go, ale bez niego jest błąd kompilacji: 'konstruktor ........ nie może sam siebie nazwać'. –

1

Jeśli to wyglądało tak:

public Curve(int degree, Point3D[] points) 
{ 
    ... 
} 

public Curve(int degree, IList<Point3D> points) 
{ 
    ... 
} 

niż można użyć: (tak długo, jak potrzebujesz tylko iterować na collec nia dla swoich zawartych Point3D s)

public Curve(int degree, IEnumerable<Point3D> points) 
{ 
    ... 
} 

Jednakże, ponieważ chcesz mieć params konstruktora, że ​​to niemożliwe do zrobienia, ponieważ nie będzie w stanie wywołać konstruktora tak:

Curve curve = new Curve(30, p1, p2, p3); 

Ale tylko tak:

Curve curve = new Curve(30, new Point3D[] {p1, p2, p3}); 

Państwo może ponownie wykorzystać swój kod za pomocą:

public Curve(int degree, params Point3D[] points) 
{ 
    ... 
} 
public Curve(int degree, IList<Point3D> points) : this(degree, points.ToArray()) { } 

lub na odwrót:

public Curve(int degree, IList<Point3D> points) 
{ 
    ... 
} 
public Curve(int degree, params Point3D[] points) : this(degree, points as IList<Point3D>) { } 

które zainicjować instancję za pomocą konstruktora params ten sam sposób, w jaki wykorzystuje jedną List .

P.S .: Czasami warto rozważyć zmianę IList do IEnumerable i tak, aby umożliwić użytkownikowi z tej klasy, aby go użyć bardziej abstrakcyjnie.

+0

To ToList w ostatnim przykładzie jest zbędne. – CSharpie

+0

Nie jest, w przeciwnym razie kompilator uważa, że ​​ten konstruktor sam siebie nazywa. –

+0

Masz rację, o tym zapomniałem. Ale lepiej jest rzucić w IList , więc nie skopiujesz całej kolekcji. – CSharpie