C# - Проблема с дженериками и наследованием

Вы пробовали oCoords / aCoords?

Это свойство должно возвращать все углы с применением поворота

http://fabricjs.com/docs/fabric .Rect.html # oCoords

http://fabricjs.com/docs/fabric.Rect.html#aCoords

Обновить [1115 ]

Поскольку вы хотите сохранить координаты для извлечения и отрисовки прямоугольника обратно из данных БД, я думаю, что лучше хранить не 4 угловые координаты, а слева, сверху, ширину, высоту, угол, масштаб. Так что вы можете создать прямоугольник в зависимости от этих свойств. Если вам это не нужно для использования в Fabricjs, вы можете использовать oCoords, о котором я упоминал ранее.

Метод

getCoords также позволяет использовать

http://fabricjs.com/docs/fabric.Rect.html#getCoords

7
задан empi 11 January 2009 в 20:27
поделиться

9 ответов

Можно только бросить от базового класса до производного класса, если объект имеет на самом деле производный класс типа. Я имею в виду, Вы не можете бросить экземпляр основы (MyClass<int>) к MyIntClass. Вы можете, однако бросить его, если это на самом деле имело тип MyIntClass сохраненный как MyClass<int> экземпляр.

MyClass<int> foo = new MyIntClass();
MyIntClass bar = (MyIntClass)foo; // this works.

Примите:

class Base {
   int x;
}

class Derived : Base {
   int y;
}

Base foo = new Base();
Derived bar = (Derived)foo;

если было позволено, из чего был бы значение bar.y быть? На самом деле, преобразование из Derived кому: Base не преобразование вообще. Это просто говорит компилятору позволять переменной типа Base указать на объект типа Derived. Это возможно, так как получено имеет больше или равные функции, чем Base который не имеет место в наоборот.

Если бы Вы смогли создать оператор преобразования между основой и производными классами, то компилятор C# не мог бы отличить ее от созданного в отношениях, определенных для них. Поэтому Вы не можете создать операторы броска вдоль иерархий наследования.

12
ответ дан 6 December 2019 в 07:28
поделиться

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

using System;

class Base {}
class Child : Base {}

class Test
{
    static void Main()
    {
        Base b = new Base();

        // This will throw an exception
        Child c = (Child) b; 
    }
}
10
ответ дан 6 December 2019 в 07:28
поделиться

Как был сказан, Вы пытаетесь бросить объект в тип, из которого он не происходит. Сделал Вас, возможно, хотят сделать это:

MyClass<int> sth = new MyIntClass(10);
MyIntClass intsth = (MyIntClass) sth;
0
ответ дан 6 December 2019 в 07:28
поделиться

В комментариях Вы спросили:

Но почему преобразование из базового класса не позволяется?

Простой - это не имело бы никакого смысла. Рассмотрите пример:

class BaseClass
{
    public int x;

    public BaseClass(int StartX)
    {
        this.x = StartX;
    }
}
class ChildClass: BaseClass
{
    public int Y;

    public BaseClass(int StartX, StartY): base(StartX)
    {
        this.y = StartY;
    }
}

class Program
{
    public static void Main()
    {
        BaseClass B = new BaseClass(3);
        ChildClass C = (ChildClass)B;
        Console.WriteLine(C.y);
    }
}

Что Вы предполагаете, что эта программа произвела бы, предположив, что бросок работал? Еще хуже - воображают это BaseClass имеет два дочерних класса - ChildClassA и ChildClassB. Вы хотите, чтобы это работало?

ChildClassA = новый ChildClassA (); BaseClass до н.э = (Базовый класс) A; ChildClassB B = (ChildClassB) до н.э;

Это эффективно позволило бы бросать ChildClassA экземпляры к ChildClassB - полностью неправильно.

2
ответ дан 6 December 2019 в 07:28
поделиться

Как указанный Mehrdad, Вы не можете удрученный объект. Upcasting неявен, поэтому Вы не можете перезаписать его.

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

Если необходимо бросить свободно, определить переменную как базовый класс, но инстанцировать производных классов.

0
ответ дан 6 December 2019 в 07:28
поделиться

Вместо того, чтобы создать MyIntClass, попробуйте псевдоним:

using MyClass<int> = What.Ever.Namespace.MyIntClass;

Это теперь допустимо:

MyClass<int> foo = new MyClass<int>();
MyIntClass bar = (MyIntClass)foo;

Просто поймите это при выполнении using псевдоним, необходимо квалифицировать пространство имен на имени типа псевдонима (Что. Когда-либо. Пространство имен).

0
ответ дан 6 December 2019 в 07:28
поделиться

Относительно Вашего второго вопроса:

Но почему я не могу создать пользовательские преобразования из базового класса?

Ну, предположите, что у Вас есть этот сценарий

class Base {
}

class Derived {
    public static operator Derived(Base b) { ... }
}

и Вы пытались сделать это

Base x = new Derived();
Derived y = (Derived)x;

преобразование нужно назвать?Конечно, нет! Значение внутри x на самом деле имеет тип Derived, таким образом, бросок является прямым без преобразования. Но если значение не имело типа Derived, но бетон Base, затем пользовательское преобразование должно произойти, потому что иначе у нас была бы ошибка компилятора. Это все не имеет никакого смысла; пользовательские преобразования найдены во время компиляции и тип значения x только известен во времени выполнения. Поэтому компилятор не знал бы, что сделать - называют пользовательское преобразование или просто бросают значение...

Надежда это имеет немного смысла Вам.

0
ответ дан 6 December 2019 в 07:28
поделиться

Ответ на последнее редактирование.

Этот код действительно уже компилирует, он только перестал работать во времени выполнения:

MyIntClass intsth = (MyIntClass) sth;

Так, следующий оператор броска был бы избыточен, если оставлено явный:

общедоступный статический неявный оператор MyIntClass (MyClass myClass)

Так, компилятор должен препятствовать тому, чтобы Вы добавили то преобразование. Я думаю, что ошибка могла бы сбивать с толку, но я думаю, что она просто запрещает класс B преобразования классу A, если B получен из (предупреждение, казалось, мне предотвратило любое преобразование в A, сначала).

Если оператор сделан неявным, это также опасно, потому что downcasting может всегда перестать работать, таким образом, Вы имеете к:

  1. покажите компилятор, что Вы знаете что путем добавления явного броска;
  2. покажите читателю (который включает себя, несколько минут спустя), который могла бы привести к сбою операция.
0
ответ дан 6 December 2019 в 07:28
поделиться

Назначение / преобразование базового класса в производный класс имеет смысл, если вы считаете, что назначение или преобразование Копия значения по значению. Что смущает в C # для newbies - это непоследовательный способ:

'int' - это 'простой' тип:

int i = 5;   // <- this creates an int.  
int j = i;    // <- this creates another int and copies the value of i into j.

'Object' - не простой тип:

Object a;                            // <- this does not create a copy of 'Object', only a reference to one
Object b = new Object();   // <- this actually creates an Object
a = b;                                 // <- this sets the reference to an object a to the reference to an object b.
                                          // both of them reference the same Object. No values were copied.

Если он делал копию значений, то копировал в базовый класс производный класс будет Работа. C # не работает, как другие языки.

Я думаю, это может вас смущать.

0
ответ дан 6 December 2019 в 07:28
поделиться
Другие вопросы по тегам:

Похожие вопросы: