Yopiq operator va umumiy sinf

Nima uchun bu C# kodi kompilyatsiya qilolmaydi?

public class X
{ }

public class Xi : X
{
    public int I { get; }
    public Xi(int i) { I = i; }
    public static implicit operator Xi(int i) { return new Xi(i); }
}

public class L : X where T : X
{
    public L(params T[] values) { }
}

public static void Main()
{
    var test1 = new L(1, 2, 3);//OK
    var test2 = new L(new int[] { 1, 2, 3 });//Unable to convert int[] into Xi
}

Yordamingiz uchun rahmat

3
Seriallar noto'g'ri kiritilmaydi.
qo'shib qo'ydi muallif Wazner, manba

6 javoblar

Sizning namunangiz bilan:

var test1 = new L(1, 2, 3);

C #, params ning har elementi ning Xi turiga ega ekanligini aniqlashga qodir. Shunday qilib, ishlab chiqarilgan kod tengdir

var test1 = new L(new Xi[] { 1, 2, 3 });

Bu erda har int yopiq tarzda Xi uchun yuboriladi va shuning uchun kodingiz ishlaydi. Biroq , ushbu kod bilan:

var test2 = new L(new int[] { 1, 2, 3 });

Siz Xi [] o'rniga int [] kodini aniq o'tkazasiz. Wazner sharhlarda ishora qilganidek, qatorlar aniq (yoki ochiq, bu holatda) mumkin emas.

2
qo'shib qo'ydi

Xi ning yangi misoli int qiymati bilan boshlanishi mumkin bo'lsa-da, int qatori Xi .

//initializing array of Xi, so for each value constructor of Xi called
Xi[] a = new Xi[] { 1, 2, 3 }; //works
//array of int is not array of Xi
Xi[] b = new int[] { 1, 2, 3 }; //fails
//1, 2, 3 are integers and anonymous array initializes as int[]
Xi[] c = new[] { 1, 2, 3 }; //fails

Array covariance works only for reference types and in the inheritance hierarchy:

Xi[] a = new Xi[] { 1, 2, 3 };
object[] b = a; //works good

int is not reference type and int does not inherits from Xi, it can be only casted to Xi.

2
qo'shib qo'ydi

Uslub ta'rifini class/struct ta'rifiga kiritishingiz kerak. Boshqaruv ta'riflari bular tashqarisida ko'rinmaydi.

   public class X
{ }

public class Xi : X
{
    public int I { get; }
    public Xi(int i) { I = i; }
    public static implicit operator Xi(int i) { return new Xi(i); }
}

public class L : X where T : X
{
    public L(params T[] values) { }

   public static void Main()
   {
       var test1 = new L(1, 2, 3);//OK
       var test2 = new L(new int[] { 1, 2, 3 });//Unable to convert int[] into Xi
   }
}
2
qo'shib qo'ydi
Shubhasiz, bu Dastur yoki oddiygina kodning turli qismlarida joylashgan bo'lishi mumkin. Bu yechimni izlayotgan OP muammo emas. Sizning kodingiz muallifning niyatiga aniq zid keladi.
qo'shib qo'ydi muallif Mikhail Neofitov, manba

You have defined a converter for int => Xi but this does not give you a converter from int[] to Xi[]

var test3 = new L(new Xi[] { 1, 2, 3 }); 

chunki int ning har biri Xi ga aylantiriladi va Xi [] ctor-ga o'tkaziladi.

0
qo'shib qo'ydi
public L(params T[] values) { }
public L(IEnumerable values) { }

Agar biz T kabi bir turni aniqlasak, tegishli turi parametri sifatida berishimiz kerak. int o'rniga Xi yoziladi.

var test2 = new L(new Xi[] { 1, 2, 3 });
0
qo'shib qo'ydi
Bu erda ortiqcha yuklangan konstruktorda hech qanday rulman yo'q - bu kod faqat ikkinchi parchadan (aniq Xi qatori int qatoridan yaratilganligi sababli)
qo'shib qo'ydi muallif Rob, manba

Muammo array Cast:

Sizning kodingiz:

public L(params T[] values) { }

va sizning chaqiruvingiz:

var test1 = new L(1, 2, 3);//OK

Xi (int i) bo'lgani uchun 1,2,3 int ga o'tkazilishi mumkin.

Boshqa tarafdan:

var test2 = new L(new int[] { 1, 2, 3 });

int ning Array , shuning uchun uni bir nechta shakllar bilan hal qilishingiz mumkin:

  • Add a new parameter in L
public L(params int[] values) { }
  • Yuklab olish Xi , ushbu ariza boshqa array xususiyatiga o'xshaydi:
public class Xi : X
{
  public int I { get; }
  public int[] Other { get; }
  public Xi(int i) { I = i; }
  public Xi(int[] i) { Other = i; }
  public static implicit operator Xi(int i) { return new Xi(i); }
}
0
qo'shib qo'ydi