Як створити елемент автоматично зразок масиву, такий як масиви int користувальницького типу?

Заявляючи масив int, такий як:

int[] test = new int[5];

Всі елементи масиву автоматично ініціалізуються на 0 . У будь-якому випадку я можу створити клас, який буде автоматично ініціалізований при створенні масиву, наприклад, масивів int?

Наприклад:

MyClass[] test2 = new MyClass[5];

Мені все одно буде потрібно зателефонувати конструктору; але за допомогою int конструктор магічно називається.

Який код/​​оператори класу int , що дозволяє це поведінку?

4
@KenKin моє початкове питання полягає в тому, як зробити клас ініціалізувати точно так само, як int. Я не отримав такої відповіді, а працював. Однак деякі з них дійсно круті і, безумовно, розглядаю їх, як і раніше, здається, відповідь, яку я отримую, на моє запитання є простим ні. Це означає, як ім'я структури, а потім [] викликає за замовчуванням конструктор. Гаразд я задам інше питання про це.
додано Автор CodeCamper, джерело
@KenKin Я розумію, що індексатори не є для екземплярів у випадку класів, а у випадку структур, які вони інстанції індексу ...
додано Автор CodeCamper, джерело
@KenKin Я розумію, що індексатори не є для екземплярів у випадку класів, а у випадку структур, які вони інстанції індексу ...
додано Автор CodeCamper, джерело
@KenKin Я начебто заплутався зараз і думаю, що моє справжнє запитання пов'язане з значеннями ініціалізації за замовчуванням і як змінити їх або створити новий тип примітиву з унікальним значенням за замовчуванням. Насправді моє запитання, мабуть, просить про те, який код відбувається всередині тих операторів індексів, які роблять їх різними. Відповідь, здається, проста, компілятор робить це, і ви не можете отримати доступ до нього, оскільки це базова структура мови подібних речей.
додано Автор CodeCamper, джерело
@KenKin Я начебто заплутався зараз і думаю, що моє справжнє запитання пов'язане з значеннями ініціалізації за замовчуванням і як змінити їх або створити новий тип примітиву з унікальним значенням за замовчуванням. Насправді моє запитання, мабуть, просить про те, який код відбувається всередині тих операторів індексів, які роблять їх різними. Відповідь, здається, проста, компілятор робить це, і ви не можете отримати доступ до нього, оскільки це базова структура мови подібних речей.
додано Автор CodeCamper, джерело
@KenKin моє початкове питання полягає в тому, як зробити клас ініціалізувати точно так само, як int. Я не отримав такої відповіді, а працював. Однак деякі з них дійсно круті і, безумовно, розглядаю їх, як і раніше, здається, відповідь, яку я отримую, на моє запитання є простим ні. Це означає, як ім'я структури, а потім [] викликає за замовчуванням конструктор. Гаразд я задам інше питання про це.
додано Автор CodeCamper, джерело
@SimonBelanger, але чому конструктор за замовчуванням не магічно викликає, коли ви просто int x; , чому він магічно викликає конструктора за замовчуванням, коли ви створюєте місце для масиву. Звичайно, у структурі, який може бути застосований до класу, повинен бути якийсь додатковий код?
додано Автор CodeCamper, джерело
@ Jordão як приходять, коли регулярний int оголошується вам потрібно викликати за замовчуванням конструктор, але коли масив int оголошений вам не потрібно викликати конструктора за умовчанням?
додано Автор CodeCamper, джерело
@ Jordão як приходять, коли регулярний int оголошується вам потрібно викликати за замовчуванням конструктор, але коли масив int оголошений вам не потрібно викликати конструктора за умовчанням?
додано Автор CodeCamper, джерело
Jordão правильно. У struct завжди є конструктор за умовчанням, де в якості класу не обмежується це обмеження.
додано Автор Simon Belanger, джерело
Зробіть MyClass структурою :-)
додано Автор Jordão, джерело
Конструктор за замовчуванням в такому випадку називається автоматично для типів значень.
додано Автор Jordão, джерело
Конструктор за замовчуванням в такому випадку називається автоматично для типів значень.
додано Автор Jordão, джерело
Зробіть MyClass структурою :-)
додано Автор Jordão, джерело
Титанік може означати корабель або фільм про цей корабель, то ми говоримо ім'я "Титанік", що це таке? Це залежить від контексту. Аналогічним чином, [] передбачає, коли ми створюємо масив, або коли ми отримуємо доступ до елемента масиву, однаковий символ, але різний зміст.
додано Автор Ken Kin, джерело
Титанік може означати корабель або фільм про цей корабель, то ми говоримо ім'я "Титанік", що це таке? Це залежить від контексту. Аналогічним чином, [] передбачає, коли ми створюємо масив, або коли ми отримуємо доступ до елемента масиву, однаковий символ, але різний зміст.
додано Автор Ken Kin, джерело
Погляньте на перевантажувальні оператори . Зверніть увагу, що квадратні дужки є не перевантажними, а індексатори є не для екземпляру.
додано Автор Ken Kin, джерело
Погляньте на перевантажувальні оператори . Зверніть увагу, що квадратні дужки є не перевантажними, а індексатори є не для екземпляру.
додано Автор Ken Kin, джерело
Якщо у вас є припущення про те, що повинен виконувати цей трюк оператором , тоді запитання з'являється незаперечним , якщо цього немає.
додано Автор Ken Kin, джерело
Якщо у вас є припущення про те, що повинен виконувати цей трюк оператором , тоді запитання з'являється незаперечним , якщо цього немає.
додано Автор Ken Kin, джерело
Попросіть одного або, принаймні, в тому ж сенсі питання на кожну посаду, це нормально. Якщо ви збираєтеся поставити інше запитання, було б краще поставити нове запитання .
додано Автор Ken Kin, джерело
new MyClass (5) ?
додано Автор Sklivvz, джерело
new MyClass (5) ?
додано Автор Sklivvz, джерело

9 Відповіді

Масовий int магічно не встановлено 0. Int - це тип значення з значенням за умовчанням 0, де як MyClass є еталонним типом з значенням за замовчуванням null .

Якщо ви хочете ініціалізувати масив з усім, ви можете використовувати метод вільного розширення:

public static T[] InitializeAll(this T[] source) where T : new()
{
    if(source != null)
    {
        for(var i = 0; i < source.Length; ++i)
        {
            source[i] = new T();
        }
    }

    return source;
}

var test2 = new MyClass[5].InitializeAll();

Або мандалека розчину, використовуючи петлю.

Редагувати: я відновлю вихідне рішення, оскільки коментар Гуффи потрібен для контексту

public static T[] CreateArray(int size) where T : new()
{
     return Enumerable.Repeat(new T(), size).ToArray();      
}
4
додано
Хм, здається, моя помилка не усвідомлює, що int - це struct , а не клас , структура автоматично за замовчуванням 0, незалежно від того, що і не існує способу перевизначити цей тип поведінки Я вважаю?
додано Автор CodeCamper, джерело
Ви абсолютно правильно. Важкий нагляд з мого боку. Я редагував своє рішення, щоб зберегти дух використання Linq, але на даний момент рішення мандалеки є найбільш ефективним.
додано Автор Simon Belanger, джерело
На жаль, немає шляху. Просто щоб виправити ще один раз, структура не обов'язково не дорівнює 0. Якщо ви створюєте власну структуру з одним властивістю int та реалізуєте конструктор за замовчуванням, який встановлює значення цього властивості до 1, тоді ваша структура з "default" для цього властивості становить 1 при ініціалізації.
додано Автор Simon Belanger, джерело
Це створить масив, повний посилань на один екземпляр, а не новий екземпляр для кожного елемента в масиві.
додано Автор Guffa, джерело

Масовий int магічно не встановлено 0. Int - це тип значення з значенням за умовчанням 0, де як MyClass є еталонним типом з значенням за замовчуванням null .

Якщо ви хочете ініціалізувати масив з усім, ви можете використовувати метод вільного розширення:

public static T[] InitializeAll(this T[] source) where T : new()
{
    if(source != null)
    {
        for(var i = 0; i < source.Length; ++i)
        {
            source[i] = new T();
        }
    }

    return source;
}

var test2 = new MyClass[5].InitializeAll();

Або мандалека розчину, використовуючи петлю.

Редагувати: я відновлю вихідне рішення, оскільки коментар Гуффи потрібен для контексту

public static T[] CreateArray(int size) where T : new()
{
     return Enumerable.Repeat(new T(), size).ToArray();      
}
4
додано
Хм, здається, моя помилка не усвідомлює, що int - це struct , а не клас , структура автоматично за замовчуванням 0, незалежно від того, що і не існує способу перевизначити цей тип поведінки Я вважаю?
додано Автор CodeCamper, джерело
На жаль, немає шляху. Просто щоб виправити ще один раз, структура не обов'язково не дорівнює 0. Якщо ви створюєте власну структуру з одним властивістю int та реалізуєте конструктор за замовчуванням, який встановлює значення цього властивості до 1, тоді ваша структура з "default" для цього властивості становить 1 при ініціалізації.
додано Автор Simon Belanger, джерело
Ви абсолютно правильно. Важкий нагляд з мого боку. Я редагував своє рішення, щоб зберегти дух використання Linq, але на даний момент рішення мандалеки є найбільш ефективним.
додано Автор Simon Belanger, джерело
Це створить масив, повний посилань на один екземпляр, а не новий екземпляр для кожного елемента в масиві.
додано Автор Guffa, джерело

Проблема полягає в тому, що MyClass є еталонним типом, тому значення за замовчуванням є нульовим. Оскільки ви не ініціалізуєте об'єкти в масиві, вони нульові. Ви можете написати помічника як:

T[] InitializeArray(int length) where T : new()
{
    T[] array = new T[length];
    for (int i = 0; i < length; ++i)
    {
        array[i] = new T();
    }

    return array;
}

а потім ініціалізувати масив:

MyClass[] something = InitializeArray(5);
4
додано

Оновлення:

Я зняв обмеження new() , щоб прийняти клас без конструктора parameterless . Однак, це також буде прийняти абстрактний клас або інтерфейс, який буде використовуватися як параметр типу, і він буде викидати виняток при виконанні, якщо тип не може бути інстанційним.

One thing further to mention is, the CreateArray method would also deal with value types; that is, except pointer types and the types which have TypeAttributes.Abstract1 attribute, you can create any type of array with it.

1: Interfaces are also abstract. Static classes are abstract & sealed.


Різниця полягає в тому, що int - це тип значення, але ваш class не може бути.

Оголошуйте MyClass як struct MyClass {} , тоді він буде вестися так само, як і ви створюєте масив int .

Якщо ви хочете створити масив типів референції, то просто виконайте наступний код:

public static class TestClass {
    public static T[] CreateArray(int length, params object[] args) {
        var elementType=typeof(T);
        var array=(T[])Array.CreateInstance(elementType, length);

        for(; length-->0;
            array[length]=(T)Activator.CreateInstance(elementType, args))
            ;

        return array;
    }

    public static void TestMethod() {
        var array=CreateArray(5, /* default arguments */ );
    }
}

Аргумент за замовчуванням - аргументи, які ви передаєте конструктору. Код створює масив, потім створює екземпляри типу з заданими аргументами та ініціалізує масив з екземплярами.

Зверніть увагу, що length передаються як розмір масиву, а потім використовуються як індекс у for-loop.

Документація:

3
додано

Оновлення:

Я зняв обмеження new() , щоб прийняти клас без конструктора parameterless . Однак, це також буде прийняти абстрактний клас або інтерфейс, який буде використовуватися як параметр типу, і він буде викидати виняток при виконанні, якщо тип не може бути інстанційним.

One thing further to mention is, the CreateArray method would also deal with value types; that is, except pointer types and the types which have TypeAttributes.Abstract1 attribute, you can create any type of array with it.

1: Interfaces are also abstract. Static classes are abstract & sealed.


Різниця полягає в тому, що int - це тип значення, але ваш class не може бути.

Оголошуйте MyClass як struct MyClass {} , тоді він буде вестися так само, як і ви створюєте масив int .

Якщо ви хочете створити масив типів референції, то просто виконайте наступний код:

public static class TestClass {
    public static T[] CreateArray(int length, params object[] args) {
        var elementType=typeof(T);
        var array=(T[])Array.CreateInstance(elementType, length);

        for(; length-->0;
            array[length]=(T)Activator.CreateInstance(elementType, args))
            ;

        return array;
    }

    public static void TestMethod() {
        var array=CreateArray(5, /* default arguments */ );
    }
}

Аргумент за замовчуванням - аргументи, які ви передаєте конструктору. Код створює масив, потім створює екземпляри типу з заданими аргументами та ініціалізує масив з екземплярами.

Зверніть увагу, що length передаються як розмір масиву, а потім використовуються як індекс у for-loop.

Документація:

3
додано

Змінити MyClass як структуру типу даних, тобто public struct MyClass .

2
додано
Я думаю, що це відповідає на моє запитання, як зробити це точно так, як int. Моя помилка - це думка, що int є класом. Тож не можна перезаписувати або встановити типовий тип значення за замовчуванням?
додано Автор CodeCamper, джерело

Змінити MyClass як структуру типу даних, тобто public struct MyClass .

2
додано
Я думаю, що це відповідає на моє запитання, як зробити це точно так, як int. Моя помилка - це думка, що int є класом. Тож не можна перезаписувати або встановити типовий тип значення за замовчуванням?
додано Автор CodeCamper, джерело

Це пов'язано з різницею між Тими значеннями та Типи довідників .

"Тип даних - це тип значення, якщо він містить дані у власному розподілі пам'яті". тоді як, "Тип посилання містить покажчик на іншу область пам'яті, яка містить дані".

Загальні приклади типів значень:

  • Усі типи числових даних
  • Булеві, символи та дати
  • Усі структури, навіть якщо їхні учасники є еталонними типами
  • Переліки, оскільки їх основний тип завжди є SByte, Short, Integer, Long, Byte, Short, UInteger або ULong

Поширені приклади типів референції:

  • String
  • All arrays, even if their elements are value types
  • Class types, such as Form
  • Delegates

Всі типи значень ініціалізуються до значення за замовчуванням (нуль для числових типів), а посилання типів - null .

Заява про:

int num;

Не ініціалізує змінну num . Тому num не можна використовувати. C# вимагає, щоб для кожної змінної було встановлено певне значення (будь то null або число) перед його використанням.

Те саме стосується типів посилання:

//un-initialized, therefore cannot be used until a value is given(A compiler error will occur)
string str;

However, Заява про:

int[] numbers = new int[5];

Викликає ініціалізований масив (тому викликається конструктором масиву), який потім ініціює кожне з елементів до значення за замовчуванням int (тобто нуль).

Використання того ж методу на еталонному типі дає той самий результат:

string[] strings = new string[5];

Викликає ініціалізацію масиву і, отже, створення масиву рядків null (це значення за замовчуванням для всіх типів посилання).

Structures are the data type that you are looking for. Structures are value types and therefore cannot be set to null. Since they cannot be set to null, they must have some default value. The default value is determined by a default constructor.

Структуру можна визначити таким чином:

struct MyStructName
{
    //Members of the struct, like a class, default value is 0.
    int myNumber;

    //Structs can have members whose data type is a reference type
    //Default value is null.
    string myString;

    //Every struct has a default constructor, though you cannot define one.
    //The compiler generates one for you that initializes every member to it's
    //default value.

}

Це визначить тип даних, який містить елементи, myNumber і myString, які не можуть бути встановлені як null .

//Array of MyStructName, the default constructor is called and each value is initialized
MyStructName[] data = new MyStructName[5];

//Loop and print results
for(int i = 0; i < data.Length; i++)
{
    //Prints the index, number and the string or "null"
    Console.WriteLine("{0}: myNumber: {1}, myString: \"{2}\"", i, data[i].myNumber, data[i].myString != null ? data[i].myString : "null"); 
}
0
додано
У конструкції struct неможливо створити конструктор без параметрів. Що таке код усередині int, який говорить, що він переходить до 0 за замовчуванням. Як замість 1 або 2? Я хочу особливо точно знати, який код викликає його ініціалізацію при розміщенні масиву. Чому створення масиву декларує конструктор, а не просто оголошує його сам по собі. Зазвичай масив не викликає конструктора за замовчуванням, тому повинен бути деякий додатковий код.
додано Автор CodeCamper, джерело
Чому структура ініціалізується, коли масив оголошений, але не тоді, коли оголошується сама структура?
додано Автор CodeCamper, джерело
Оскільки їх не можна встановити як значення null, вони повинні мати деяке значення за замовчуванням. Таким чином, клас, який не може бути нульовим, може бути встановлений як нуль? Чи всі класи називаються нульовою?
додано Автор CodeCamper, джерело
З цікавості, оскільки ви згадали про C#, чи знаєте ви, будь-які загальні мови, такі як Java, які підтримують цю функцію?
додано Автор CodeCamper, джерело
Усі класи можна встановити на нуль. Структура не може бути нульовою. Ви не просто визначаєте масиву. Ключове слово new викликає ініціалізацію нового масиву, тому викликає ініціалізацію кожного елемента. У C# відсутній спеціальний код, який викликає виклик конструктора для інтерґраторів, код для Int32 має внутрішній член, тип якого int . Вибачте за конструктором за умовчанням (параметр менше) (C # не дозволяє визначити його), я його видалив.
додано Автор AtinSkrita, джерело
Вибачте, але не дуже. Java не підтримує те, що ви хочете, оскільки ви не можете визначити тип значення (структури), лише типи рефералів (класів). Найкраще, що я можу думати про ініціалізацію за замовчуванням, - це написати метод розширення, подібний до цього public T [] Initialize (цей масив T [], де T: new() , а потім всередині Метод петлі через елементи масиву та викликати конструктор за замовчуванням. Це буде працювати для класів за допомогою конструктора за умовчанням. Тоді ви називаєте це як будь-який метод розширення. myArray.Initialize()
додано Автор AtinSkrita, джерело

Це пов'язано з різницею між Тими значеннями та Типи довідників .

"Тип даних - це тип значення, якщо він містить дані у власному розподілі пам'яті". тоді як, "Тип посилання містить покажчик на іншу область пам'яті, яка містить дані".

Загальні приклади типів значень:

  • Усі типи числових даних
  • Булеві, символи та дати
  • Усі структури, навіть якщо їхні учасники є еталонними типами
  • Переліки, оскільки їх основний тип завжди є SByte, Short, Integer, Long, Byte, Short, UInteger або ULong

Поширені приклади типів референції:

  • String
  • All arrays, even if their elements are value types
  • Class types, such as Form
  • Delegates

Всі типи значень ініціалізуються до значення за замовчуванням (нуль для числових типів), а посилання типів - null .

Заява про:

int num;

Не ініціалізує змінну num . Тому num не можна використовувати. C# вимагає, щоб для кожної змінної було встановлено певне значення (будь то null або число) перед його використанням.

Те саме стосується типів посилання:

//un-initialized, therefore cannot be used until a value is given(A compiler error will occur)
string str;

However, Заява про:

int[] numbers = new int[5];

Викликає ініціалізований масив (тому викликається конструктором масиву), який потім ініціює кожне з елементів до значення за замовчуванням int (тобто нуль).

Використання того ж методу на еталонному типі дає той самий результат:

string[] strings = new string[5];

Викликає ініціалізацію масиву і, отже, створення масиву рядків null (це значення за замовчуванням для всіх типів посилання).

Structures are the data type that you are looking for. Structures are value types and therefore cannot be set to null. Since they cannot be set to null, they must have some default value. The default value is determined by a default constructor.

Структуру можна визначити таким чином:

struct MyStructName
{
    //Members of the struct, like a class, default value is 0.
    int myNumber;

    //Structs can have members whose data type is a reference type
    //Default value is null.
    string myString;

    //Every struct has a default constructor, though you cannot define one.
    //The compiler generates one for you that initializes every member to it's
    //default value.

}

Це визначить тип даних, який містить елементи, myNumber і myString, які не можуть бути встановлені як null .

//Array of MyStructName, the default constructor is called and each value is initialized
MyStructName[] data = new MyStructName[5];

//Loop and print results
for(int i = 0; i < data.Length; i++)
{
    //Prints the index, number and the string or "null"
    Console.WriteLine("{0}: myNumber: {1}, myString: \"{2}\"", i, data[i].myNumber, data[i].myString != null ? data[i].myString : "null"); 
}
0
додано
У конструкції struct неможливо створити конструктор без параметрів. Що таке код усередині int, який говорить, що він переходить до 0 за замовчуванням. Як замість 1 або 2? Я хочу особливо точно знати, який код викликає його ініціалізацію при розміщенні масиву. Чому створення масиву декларує конструктор, а не просто оголошує його сам по собі. Зазвичай масив не викликає конструктора за замовчуванням, тому повинен бути деякий додатковий код.
додано Автор CodeCamper, джерело
Чому структура ініціалізується, коли масив оголошений, але не тоді, коли оголошується сама структура?
додано Автор CodeCamper, джерело
Оскільки їх не можна встановити як значення null, вони повинні мати деяке значення за замовчуванням. Таким чином, клас, який не може бути нульовим, може бути встановлений як нуль? Чи всі класи називаються нульовою?
додано Автор CodeCamper, джерело
З цікавості, оскільки ви згадали про C#, чи знаєте ви, будь-які загальні мови, такі як Java, які підтримують цю функцію?
додано Автор CodeCamper, джерело
Усі класи можна встановити на нуль. Структура не може бути нульовою. Ви не просто визначаєте масиву. Ключове слово new викликає ініціалізацію нового масиву, тому викликає ініціалізацію кожного елемента. У C# відсутній спеціальний код, який викликає виклик конструктора для інтерґраторів, код для Int32 має внутрішній член, тип якого int . Вибачте за конструктором за умовчанням (параметр менше) (C # не дозволяє визначити його), я його видалив.
додано Автор AtinSkrita, джерело
Вибачте, але не дуже. Java не підтримує те, що ви хочете, оскільки ви не можете визначити тип значення (структури), лише типи рефералів (класів). Найкраще, що я можу думати про ініціалізацію за замовчуванням, - це написати метод розширення, подібний до цього public T [] Initialize (цей масив T [], де T: new() , а потім всередині Метод петлі через елементи масиву та викликати конструктор за замовчуванням. Це буде працювати для класів за допомогою конструктора за умовчанням. Тоді ви називаєте це як будь-який метод розширення. myArray.Initialize()
додано Автор AtinSkrita, джерело
var chat = new Chat();
var chat = new Chat();
642 учасників

Обсуждение вопросов по C# / .NET / .NET Core / .NET Standard / Azure Сообщества-организаторы: — @itkpi — @dncuug