универсальное наследование в C#? [дубликат]

Вы хотите разделить свои данные на обучающие и тестовые наборы. Для этого вы можете либо

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

  2. Загрузка целых данных и разделение их для обучения и проверки в памяти.

Давайте обсудим второй вариант.

главный каталог содержит 40 подкаталогов

Предположим, что ваш главный каталог - Train//, и есть 40 подпапок, а именно 1-40. Кроме того, я предполагаю, что метка класса - это имя папки.

# imports

import cv2
import numpy as np
import os

from sklearn.model_selection import train_test_split

# seed for reproducibility
SEED = 44000


# lists to store data
data = []
label = []

# folder where data is placed
BASE_FOLDER = 'Train//'

folders = os.listdir(BASE_FOLDER)

# loading data to lists
for folder in folders:
    for file in os.listdir(BASE_FOLDER + folder + '//'):
        img = cv2.imread(BASE_FOLDER + folder + '//' + file)
        # do any pre-processing if needed like resize, sharpen etc.
        data = data.append(img)
        label = label.append(folder)

# now split the data in to train and test with the help of train_test_split

train_data, test_data, train_label, test_label = train_test_split(data, label, test_size=0.2, random_state=SEED)
11
задан Community 23 May 2017 в 12:00
поделиться

7 ответов

You could do something like

public interface IXyzable { void xyz(); }

public class MyGenericClass<T> : IXyzable where T : IXyzable {
    T obj;
    public void xyz() {
        obj.xyz();
    }
}

Edit: Now I understand the question

5
ответ дан 3 December 2019 в 05:36
поделиться

Это невозможно, потому что в зависимости от типа T открытый интерфейс MyGenericClass изменится.

Если у вас много разных классов, которые все предоставляют один и тот же интерфейс, вы можете объявить MyGenericClass предоставляет этот интерфейс, а при реализации всех функций делегирует вызовы obj

9
ответ дан 3 December 2019 в 05:36
поделиться

Вам понадобятся все возможные Т для реализации некоторого интерфейса, чтобы вы знали, что obj.XYZ () имеет смысл , тогда вы можете сделать

public interface Ixyz
{
    void XYZ();
}

public class MyGenericClass<T> : Ixyz where T:Ixyz, new()
{
    T obj;

    public MyGenericClass()
    {
        obj = new T();
    }

    public void XYZ()
    {
        obj.XYZ();
    }
}

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

var x = new MyGenericClass<MyGenericClass<SomeClass>>();

, что вряд ли когда-нибудь будет хорошей идеей.

1
ответ дан 3 December 2019 в 05:36
поделиться

Конкретный вопрос, почему вы не можете сделать это:

public class MyGenericClass<T> : T

И вы можете сделать это:

public class MyGenericClass<T> 
{
   T obj;
}

Причина в том, что CLR нравится иметь возможность компилировать единственную версию кода для MyGenericClass, которая будет работать для любого ссылочного типа, указанного для T.

Он может сделать это для второго случая, потому что он может спокойно заменить T с объектом и вставкой соответствующих приведений, примерно эквивалентных:

public class MyGenericClass 
{
   object obj;
}

Но для версии наследования этот трюк не работает.

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

class MyBase 
{
    public virtual void MyVirtual() { }
}

class MyGenericDerived<T> : T
{
    public override void MyVirtual() 
    {
        Console.WriteLine("Overridden!"); 
    }
} 

MyBase obj = new MyGenericDerived<MyBase>();
obj.MyVirtual();

То, что я хочу сделать, это что-то вроде «смешивания», где MyGenericDerived предоставляет определения для виртуальных функций в любой базе, к которой они применяются. Но как компилятор узнает, что у T будет метод MyVirtual, который можно переопределить? Мне нужно наложить ограничение на T. Как бы я выразил это через интерфейсы? Это невозможно. Использование интерфейсов для описания ограничений не является адекватным решением, если вы разрешаете наследование от параметров типа. Так что это еще одна причина, почему он не существует в языке сегодня.

t адекватное решение, если вы разрешите наследование от параметров типа. Так что это еще одна причина, почему он не существует в языке сегодня.

t адекватное решение, если вы разрешите наследование от параметров типа. Так что это еще одна причина, почему он не существует в языке сегодня.

5
ответ дан 3 December 2019 в 05:36
поделиться

Как насчет этого:

class BaseClass<T>
{
    public T property { get; set; }
}

class GenericClass<T> : BaseClass<T>
{ 

}

class Program
{
    static void Main(string[] args)
    {
        GenericClass<int> l = new GenericClass<int>();
        l.property = 10;
    }
}

Это позволяет достичь того, что вы хотите сделать?

0
ответ дан 3 December 2019 в 05:36
поделиться

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

class BaseGeneric<T>
{
    private T obj;
    private MethodInfo mi;
    private const string MethodNameOfInterest = "Xyz";

    public BaseGeneric(T theObject)
    {
        this.obj = theObject;
        Type t = obj.GetType();
         mi = t.GetMethod(MethodNameOfInterest);
    }

    public void Xyz()
    {
        mi.Invoke(obj, null);
    }
}   

Конечно, вам нужно будет добавить намного больше для проверки ошибок и тому подобного, но это суть того, что вы могли бы сделать. Также не забудьте добавить пространство имен System.Reflection в ваше предложение using.

1
ответ дан 3 December 2019 в 05:36
поделиться

Тип .NET Система не разрешает объявления типов в той форме, которую вы пытаетесь. Одна из причин, по которой это запрещено, должна быть интуитивно понятной: как MyGenericClass будет действовать, когда T является запечатанным классом (например, система ). String )?

Если вам абсолютно необходимы эти функции (и вы знаете, что тип T , который вы будете использовать, не запечатан), вы можете генерировать прокси во время выполнения, используя классы в пространство имен Reflection.Emit . Также возможно достичь этого эффекта, используя такие инструменты АОП, как PostSharp.

0
ответ дан 3 December 2019 в 05:36
поделиться
Другие вопросы по тегам:

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