C# Generi c метод генерации случайных чисел - PullRequest
2 голосов
/ 30 мая 2020

Вижу, что для C ++ есть аналогичный вопрос. Кто-нибудь знает, почему этот метод работает, когда метод не является универсальным c, но как только я сделаю его универсальным c, часть кода со случайными числами не работает? Ошибка: невозможно неявно преобразовать тип int в 'T'. Если я не могу использовать дженерики, мне придется переписывать одну и ту же функцию снова и снова для каждой разной длины массива.

public void fillGenericArray<T>(T[] inputArray) where T : IComparable
{
    var randomNumb1 = new Random();

    for (int i = 0; i < inputArray.Length - 1; i++)
    {
        Console.WriteLine($"{inputArray[i] = randomNumb1.Next(1, 501)},");
    }
}

Ответы [ 2 ]

2 голосов
/ 30 мая 2020

Мне пришлось дважды посмотреть на это, но вот в чем проблема:

Потому что inputArray - это «массив типа T»

, тогда хотя i - это int выражение

inputArray[i] 

возвращает тип T, а не тип int.

И наоборот, ему должен быть присвоен тип T.

Общий c метод, подобный этому, может достичь вашей цели:

public static void fillGenericArray<T>(T[] inputArray)
{
    for (int i = 0; i < inputArray.Length; i++)
    {
        // Where T has a CTor that takes an int as an argument
        inputArray[i] = (T)Activator.CreateInstance(typeof(T), Random.Next(1, 501));
    }
}

(Спасибо to это сообщение SO для освежения моей памяти о создании экземпляра T с аргументами.)

Вы также можете использовать Enumerable.Range (), чтобы получить тот же результат без написания метода вообще:

// Generically, for any 'SomeClass' with a CTor(int value)
SomeClass[] arrayOfT = 
    Enumerable.Range(1, LENGTH).Select(i => new SomeClass(Random.Next(1, 501)))
    .ToArray();

(Слегка Изменено с помощью это сообщение SO ) - см. ответ с помощью Enumerable.Range ().

Вот тестовый бегун:

class Program
{
    static Random Random { get; } = new Random();
    const int LENGTH = 10;
    static void Main(string[] args)
    {

        Console.WriteLine();
        Console.WriteLine("With a generic you could do this...");


        SomeClass[] arrayOfT;
        arrayOfT = new SomeClass[LENGTH];
        fillGenericArray<SomeClass>(arrayOfT);
        Console.WriteLine(string.Join(Environment.NewLine, arrayOfT.Select(field=>field.Value)));


        Console.WriteLine();
        Console.WriteLine("But perhaps it's redundant, because Enumerable is already Generic!");

        arrayOfT = Enumerable.Range(1, LENGTH).Select(i => new SomeClass(Random.Next(1, 501))).ToArray();
        Console.WriteLine(string.Join(Environment.NewLine, arrayOfT.Select(field => field.Value)));

        // Pause
        Console.WriteLine(Environment.NewLine + "Any key to exit");
        Console.ReadKey();
    }
    public static void fillGenericArray<T>(T[] inputArray)
    {
        for (int i = 0; i < inputArray.Length; i++)
        {
            inputArray[i] = (T)Activator.CreateInstance(typeof(T), Random.Next(1, 501));
        }
    }
    class SomeClass
    {
        public SomeClass(int value)
        {
            Value = value;
        }
        public int Value { get; set; }
    }
}

Console Output

Клонировать или загрузить этот пример с GitHub.

1 голос
/ 30 мая 2020

Нет причин использовать дженерики. Просто замените T на int, и у вас будет функция, которая делает то, что вы хотите (на основе вашего вопроса и комментария под ним).

EDIT: из вашего комментария кажется, что вы неправильно понимаете цель дженериков. Функция non-generi c БУДЕТ работать для всех длин массива.

И чтобы ответить, почему не удается перейти на дженерики. Вы пытаетесь присвоить int generi c type T, который может быть любым, и компилятор не разрешит такое приведение.

...