Я могу постараться не бросать перечисление значений, когда я пытаюсь использовать или возвратить его?

Скомпилировано и интерпретировано

«Когда исходный код переведен»

  • Исходный код: исходный код (обычно вводимый человеком в компьютер)
  • Перевод: Преобразование исходного кода в то, что компьютер может прочитать (т.е. машинный код)
  • Время выполнения: Период, когда программа выполняет команды (после компиляции, если скомпилировано)
  • Скомпилированный язык: код, переведенный до времени выполнения
  • Интерпретированный язык: код, переведенный «на лету» во время исполнения

Ввод текста

Когда типы проверяются «

5 + '3' является примером ошибки типа в сильно типизированных языках , таких как Go и Python, потому что они не допускают« принуждение типа », -> способность значения изменять тип в определенных контекстах, например, слияние двух типов. Слабо напечатанные языки , такие как JavaScript, не будут вызывать ошибку типа (результаты в '53').

  • Статический: типы проверяются перед временем выполнения
  • Динамический: типы проверяются «на лету» во время исполнения

Определения «Static & amp; compiled» и «Dynamic & amp; Interpreted» весьма схожи. . но помните, что это «когда типы проверены» и «когда исходный код переводится».

Вы получите ошибки одного и того же типа независимо от того, скомпилирован или интерпретирован язык!


Пример Python

Динамический, интерпретированный

def silly(a):
    if a > 0:
        print 'Hi'
    else:
        print 5 + '3'

silly(2)

Поскольку Python интерпретируется и динамически типизируется, он только переводит и вводит код проверки, в котором он выполняется. Блок else никогда не выполняется, поэтому 5 + '3' никогда даже не смотрится!

Что делать, если он был статически введен?

Ошибка типа быть выброшенным до того, как код будет запущен.

Что делать, если он был скомпилирован?

Блок else будет выглядеть так, как если бы он был интерпретирован. переводится / просматривается до запуска, но поскольку он динамически набирается, он не будет вызывать ошибку! Динамически типизированные языки не проверяют типы до выполнения, и эта строка никогда не выполняется.


Перейти Пример

Статический, скомпилированный

package main

import ("fmt"
)

func silly(a int) {
  if (a > 0) {
      fmt.Println("Hi")
  } else {
      fmt.Println("3" + 5)
  }
}

func main() {
  silly(2)
}

типы проверяются перед запуском (статические), и ошибка типа сразу же попадает! Типы все еще проверялись до времени выполнения, если они были интерпретированы, имея тот же результат. Если он был динамическим, он не выдавал бы никаких ошибок, даже несмотря на то, что во время компиляции будет рассмотрен код.


Производительность

Скомпилированный язык будет иметь лучшую производительность при запуске -time, если он статически типизирован (по сравнению с динамическим); знание типов допускает оптимизацию машинного кода.

Статически типизированные языки имеют лучшую производительность во время выполнения по существу из-за того, что не требуется динамически проверять типы во время выполнения (он проверяет перед запуском).

Аналогично, скомпилированные языки быстрее во время выполнения, поскольку код уже был переведен вместо необходимости «интерпретировать» / переводить его на лету.

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


Дополнительные отличия

Статическая типизация задерживает ошибки раньше, а не находит их во время выполнения (особенно полезно для длинных программ). Это более «строгий», поскольку он не допускает ошибок типа в любом месте вашей программы и часто предотвращает изменение переменных типов, что еще больше защищает от непреднамеренных ошибок.

num = 2
num = '3' // ERROR

Динамическая типизация более гибкая, которые некоторые ценят. Обычно это позволяет переменным изменять типы, что может привести к неожиданным ошибкам.

28
задан Mark Carpenter 23 February 2009 в 15:13
поделиться

7 ответов

перечисления, как предполагается, безопасны с точки зрения типов. Я думаю, что они не сделали их неявно castable для воспрепятствования другого использования. Хотя платформа позволяет Вам присваивать постоянную величину им, необходимо пересмотреть намерение. Если Вы, прежде всего, используете перечисление для хранения постоянных величин, рассматриваете использование статического класса:

public static class ReturnValue
{
    public const int Success = 0;
    public const int FailReason1 = 1;
    public const int FailReason2 = 2;
    //Etc...
}

, Который позволяет Вам сделать это.

public static int main(string[] args){
    return ReturnValue.Success;
}

РЕДАКТИРОВАНИЕ

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

[Flags] // indicates bitwise operations occur on this enum
public enum DaysOfWeek : byte // byte type to limit size
{
    Sunday = 1,
    Monday = 2,
    Tuesday = 4,
    Wednesday = 8,
    Thursday = 16,
    Friday = 32,
    Saturday = 64,
    Weekend = Sunday | Saturday,
    Weekdays = Monday | Tuesday | Wednesday | Thursday | Friday
}

Это перечисление может затем быть использовано при помощи поразрядной математики. Посмотрите ниже примера для некоторых приложений.

public static class DaysOfWeekEvaluator
{
    public static bool IsWeekends(DaysOfWeek days)
    {
        return (days & DaysOfWeek.Weekend) == DaysOfWeek.Weekend;
    }

    public static bool IsAllWeekdays(DaysOfWeek days)
    {
        return (days & DaysOfWeek.Weekdays) == DaysOfWeek.Weekdays;
    }

    public static bool HasWeekdays(DaysOfWeek days)
    {
        return ((int) (days & DaysOfWeek.Weekdays)) > 0;
    }

    public static bool HasWeekendDays(DaysOfWeek days)
    {
        return ((int) (days & DaysOfWeek.Weekend)) > 0;
    }
}
49
ответ дан Michael Meadows 14 October 2019 в 10:48
поделиться

Нет никакого неявного броска, потому что перечисление не должно использовать интервал в качестве базового типа. Если Ваше перечисление использовало uint в качестве базового типа, например, нет никакого неявного броска от uint до интервала

3
ответ дан tvanfosson 14 October 2019 в 10:48
поделиться

Перечисления и ints просто не неявно castable согласно спецификации (за исключением литерального 0, который позволяется для сравнительных испытаний / присвоения / и т.д.). Явный бросок - все, что необходимо, все же.

2
ответ дан Marc Gravell 14 October 2019 в 10:48
поделиться

Нет, Вы не можете постараться не бросать; относительно того, почему нет никакого неявного преобразования, я не знаю, но нет.

0
ответ дан mqp 14 October 2019 в 10:48
поделиться

Можно приписать это поведение основному намерению позади создания Перечислений... для создания ряда именованных констант, которые могли только указать (или значение по умолчанию) значения в зависимости от базового типа.

существует два отдельных вопроса для рассмотрения, как связано с вопросом:

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

  2. Кастинг становится необходимым, так как Вы пытаетесь преобразовать из управляющего типа (типа YourCustomEnum, который происходит из System.Enum класс) к базовому типу, т.е. int или byte, и т.д.

0
ответ дан Cerebrus 14 October 2019 в 10:48
поделиться

Странно достаточно это не характерно для Платформы.NET, но только для C#. Как другие комментаторы уже указали в C#, это - в основном спецификация языка. То же не верно в VB.NET.

Выезд ссылочная страница MSDN для Перечисления в VB.NET . Обратите внимание, что можно указать тип данных перечисления в Перечислимое время объявления.

, Который означает, если Вы действительно не хотите замусорить свой код бросками к (интервалу), Вы могли записать свое перечисление в VB.NET, объявить это как целое число, затем использовать то Перечисление от C#.

Помнят, как они сказали нам, что компьютеры сделают наши жизни настолько более простыми? :)

0
ответ дан Mike 14 October 2019 в 10:48
поделиться

По какой-то причине API-интерфейс Flash Player не отображает точку регистрации DisplayObjects (а Flash IDE затрудняет их изменение после создания объекта). Лучшее решение, как указал Дэвид, - добавить ваш компонент как дочерний элемент другого компонента ( UIComponent будет в порядке). Так, например, если бы у меня была кнопка , и я хотел, чтобы ее точка регистрации находилась в ее центре, я бы добавил ее как дочерний элемент UIComponent (не Canvas ) и сместить дочерний элемент, установив его положение в (- button.width / 2, -button.height / 2) .

Конструктор должен выполнить значение через делегат ограничения и выдать исключение, если оно не соответствует ограничению. Базовый класс должен также заботиться о неявной операции преобразования в T и должен обрабатывать равенство, перегружая object.Equals (object) и object.GetHashCode (), определяя операторы == и! = Для типа ConstrainedNumber и реализации IEquatable и IEquatable > . Я также рекомендую определить конструктор копирования для базового класса и всех производных типов. Затем клонирование может быть чисто реализовано в базовом классе путем извлечения конструктора копирования с помощью отражения, но это совершенно необязательно. Вы можете сами понять реализацию ConstrainedNumber , если я не мы уже разместили его где-то в stackoverflow.

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

public sealed class ReturnValue: ConstrainedNumber<int>
{
    public static readonly NumberConstraint<int> constraint = (int x) => (x >= 0 && x < 3);

    public static readonly ReturnValue Success = new ReturnValue(0);
    public static readonly ReturnValue FailReason1 = new ReturnValue(1);
    public static readonly ReturnValue FailReason2 = new ReturnValue(2);

    private ReturnValue( int value ): base( value, constraint ) {}
    private ReturnValue( ReturnValue original ): base (original) {} //may be used to support IClonable implementation in base class
    public static explicit operator ReturnValue( int value )
    {
        switch(value) //switching to return an existing instance is more efficient than creating a new one and re-checking the constraint when there is a limited number of allowed values; if the constraint was more generic, such as an even number, then you would instead return a new instance here, and make your constructors public.
        {
            case 0: return Success;
            case 1: return FailReason1;
            case 2: return FailReason2;
        }
        throw new ArgumentException( "Value fails to meet the constraint defined for " + typeof(ReturnValue).FullName + ".", "value" );
    }

}

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

Это можно использовать так:

EvenNumber x = (EvenNumber)2;
EvenNumber y = (EvenNumber)3; //throws exception "Value fails to meet the constraint defined for {namespace}.EvenNumber."  A c# enum would stupidly allow such a cast, creating an invalid EvenNumber, breaking the object-oriented model
int z = x; //implicit conversion, no cast necessary;
3
ответ дан Triynko 28 November 2019 в 03:04
поделиться
Другие вопросы по тегам:

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