C#: Объявление и использование списка универсальных классов с различными типами, как?

Я думаю, что вы можете использовать np.where , чтобы найти, где df.day равно 20, и получить значение 28, 29 и 30, в зависимости от случая, это на самом деле, где df.day равно df.month_total_days, за исключением случаев, когда df.month_total_days больше 30, поэтому вы можете использовать, например, pd.clip_upper , чтобы иметь 30 вместо любого значения, превышающего

.

import numpy as np

df['is_payday'] = np.where( (df.day == 20) | 
                            (df.day == df.month_total_days.clip_upper(30), 1, 0)

27
задан jgauffin 29 August 2010 в 14:25
поделиться

8 ответов

Я думаю проблема, которую Вы имеете, то, потому что Вы пытаетесь создать универсальный тип и затем создать список того универсального типа. Вы могли выполнить то, что Вы пытаетесь сделать, выходя из типов данных, которые Вы пытаетесь поддерживать, сказать как элемент IData и затем создать Ваш MyData, универсальный с ограничением IData. Оборотная сторона к этому была бы то, что необходимо будет создать собственные типы данных для представления всех примитивных типов данных, которые Вы используете (строка, интервал, плавание, долго). Это могло бы выглядеть примерно так:

public class MyData<T, C>
    where T : IData<C>
{
    public T Data { get; private set; }

    public MyData (T value)
    {
         Data = value;
    }
}

public interface IData<T>
{
    T Data { get; set; }
    void SomeMethod();
}

//you'll need one of these for each data type you wish to support
public class MyString: IData<string>
{
   public MyString(String value)
   {
       Data = value;
   }

   public void SomeMethod()
   {
       //code here that uses _data...
       Console.WriteLine(Data);
   }

   public string Data { get; set; }
}

и затем Вы - реализация, было бы что-то как:

var myData = new MyData<MyString, string>(new MyString("new string"));    
// Could be MyString, MyInt, ...
myData.Data.SomeMethod();

это - немного больше работы, но Вы получаете функциональность, для которой Вы шли.

ОБНОВЛЕНИЕ: удаляют SomeMethod из Вашего интерфейса и просто делают это

SomeMethod(myData.Data.Data);
13
ответ дан Joseph 28 November 2019 в 05:38
поделиться

Просто используйте ArrayList и забудьте эти MyData<T> тип.

ArrayList myStuff = getStuff();
float x = myStuff.OfType<float>().First();
SomeMethod(x);
string s = myStuff.OfType<string>().First();
SomeMethod(s);

проблема с MyData<T> состоит в том, что Вы ожидаете, что компилятор проверит тип, который только известен во времени выполнения. Компиляторы проверяют типы, которые известны во время компиляции.

6
ответ дан Amy B 28 November 2019 в 05:38
поделиться

Вы не можете сделать этого способ, которым Вы хотите.

, Когда экземпляр универсального класса инициализируется, он связывается с конкретным типом. Так как Вы хотите держать объекты различных типов в Вашем списке, необходимо создать экземпляр, связанный с наименее общим знаменателем — в случае, это - Объект.

Однако, который означает, что Свойство данных теперь возвратит объект текстового объекта. Компилятор не может вывести фактический тип данных во время компиляции, таким образом, он может выбрать соответствующее SomeMethod перегрузка.

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

Или можно пойти со стандартом IEnumerable набор (как Массив) и использовать OfType<> дополнительный метод для получения подмножества набора конкретного типа.

3
ответ дан Lernkurve 28 November 2019 в 05:38
поделиться

В этом случае Вам нужно MyData<object>, так как это - единственная вещь, которую имеют общего те типы.

1
ответ дан AnthonyWJones 28 November 2019 в 05:38
поделиться

Можно создать универсальную обертку для SomeMethod и проверить на тип универсального аргумента, затем делегировать к соответствующему методу.

public void SomeMethod<T>(T value)
{
    Type type = typeof(T);

    if (type == typeof(int))
    {
        SomeMethod((int) (object) value); // sadly we must box it...
    }
    else if (type == typeof(float))
    {
        SomeMethod((float) (object) value);
    }
    else if (type == typeof(string))
    {
        SomeMethod((string) (object) value);
    }
    else
    {
        throw new NotSupportedException(
            "SomeMethod is not supported for objects of type " + type);
    }
}
1
ответ дан Hosam Aly 28 November 2019 в 05:38
поделиться

Предложенные подстановочные знаки некоторое время назад здесь . Закрытый как "не зафиксирует": (

1
ответ дан Tim Cooper 28 November 2019 в 05:38
поделиться

Дженерики позволяют Вам определять один тип для целого списка при создании списка например, список для хранения интервала был бы создан как это

var myData = new MyData<int>();

, Если Вы хотите сохранить несколько типов в том же универсальном списке, можно определить тип общей базы или интерфейс для тех типов. К сожалению, в Вашем случае единственный тип общей базы для типов, которые Вы хотите сохранить, был бы объектом.

var myData = new MyData<object>();

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

0
ответ дан Mendelt 28 November 2019 в 05:38
поделиться

Наследуйте MyData<T> от недженерика MyData класс и составьте список этого.

Таким образом, Вы не можете автоматически разрешить перегрузку. Необходимо сделать это вручную.

abstract class MyData { 
   protected abstract object GetData();
   protected abstract Type GetDataType(); 
   public object Data {
      get { return GetData(); } 
   }
   public Type DataType {
      get { return GetDataType(); } 
   }
}

class MyData<T> : MyData { 
   protected override object GetData() { return Data; }
   protected override Type GetDataType() { return typeof(T); }
   public new T Data {
     get { ... }
   }
}
0
ответ дан Mehrdad Afshari 28 November 2019 в 05:38
поделиться
Другие вопросы по тегам:

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