C # эквивалентно VC.NET DirectCast?

Раньше мы сохраняли DB пользователя / pass в файле конфигурации, но с тех пор попадали в параноидальный режим - применяя политику Defense in Depth .

Если ваше приложение скомпрометировано , пользователь получит доступ к вашему конфигурационному файлу и, следовательно, есть вероятность, что взломщик сможет прочитать эту информацию. Файлы конфигурации также могут попасть в управление версиями или скопировать серверы.

Мы переключились на сохранение пользовательских / pass в переменных среды, установленных в Apache VirtualHost. Эта конфигурация читается только root: надеюсь, что ваш пользователь Apache не работает как root.

Кон таким образом, что теперь пароль находится в глобальной переменной PHP.

To смягчите этот риск, мы имеем следующие меры предосторожности:

  • Пароль зашифрован. Мы расширяем класс PDO, чтобы включить логику для дешифрования пароля. Если кто-то читает код, где мы устанавливаем соединение, не будет очевидно, что соединение устанавливается с зашифрованным паролем, а не с самим паролем.
  • Зашифрованный пароль перемещается из глобальных переменных в частная переменная Приложение делает это немедленно, чтобы уменьшить окно, доступное в глобальном пространстве.
  • phpinfo() отключен. PHPInfo - это легкая цель получить обзор всего, включая переменные среды.
49
задан Peter Mortensen 29 June 2017 в 20:53
поделиться

10 ответов

Кажется очевидным, что нужная вам функциональность отсутствует в C #. Хотя попробуйте это ...

static T DirectCast<T>(object o, Type type) where T : class
{
    if (!(type.IsInstanceOfType(o)))
    {
        throw new ArgumentException();
    }
    T value = o as T;
    if (value == null && o != null)
    {
        throw new InvalidCastException();
    }
    return value;
}

Или, даже если он отличается от VB, назовите это так:

static T DirectCast<T>(object o) where T : class
{
    T value = o as T;
    if (value == null && o != null)
    {
        throw new InvalidCastException();
    }
    return value;
}
13
ответ дан 7 November 2019 в 11:57
поделиться

VB.NET:

Dim xxx as label = Directcast(sender, label)

C#:

label xxx = (label)sender;
1
ответ дан 7 November 2019 в 11:57
поделиться

Вы можете реализовать это самостоятельно:

static T CastTo<T>(this object obj) { return (T)obj; }

Используется следующим образом:

3.5.CastTo<int>(); //throws InvalidCastException.

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

1
ответ дан 7 November 2019 в 11:57
поделиться

Позвольте мне попробовать сделать это.

Во-первых, позвольте мне прояснить это. Этот НЕ БУДЕТ компилироваться:

//This code uses a type converter to go across an inheritance tree
string s = "10";
int i = (int)s;

VB CType

В VB вы должны использовать:

Dim s as String = "10"
Dim i as Integer = CType(s, Integer)

В C # я бы использовал:

string s = "10";
int i = Convert.ToInt32(s);

VB DirectCast

Если это правильный тип , приведите его, в противном случае выбросите InvalidCastException.

Прямое приведение может идти только вверх или вниз по ветке , но никогда не может переходить в другую ветку.

Исходя из этого объяснения, это был бы прямой эквивалент преобразования C #. Однако в C # вам нужно будет указать только оператор приведения только для приведения. Кастинг совершенно не обязателен. Пример:

// casting down
object t = "some random string needing to be casted down";
string s = (string) t;
// casting up
object a = s;
// explicitly casting up although it's totally optional
object b = (object) s;

Приведение C # не ищет никаких преобразователей типов. Он будет искать только любую определенную явную / неявную перегрузку оператора для типа, к которому вы пытаетесь привести.


VB TryCast

Вы уже правильно поняли, что это эквивалентно ключевому слову C # as.

0
ответ дан 7 November 2019 в 11:57
поделиться

У вас есть два типа приведения в C #. Без дополнительного кода нет эквивалента ключевому слову DirectCast в C #. Самое близкое, что у вас есть, не создавая его самостоятельно, - это использовать () .

У вас есть:

My_Object c = (My_Object)object

и

My_Object c = object as My_Object

В первом случае, если приведение не удается, выдается ошибка. Вы говорите: «Я знаю, что это за объект, и если это не так, что-то не так».

Во втором, c присваивается значение null, где это возможно (null не может быть присвоенными типам значений). В этом вы говорите: «Думаю, я знаю, что это, но если нет, не выдает ошибку, потому что все может быть неправильно».

Другой пост, объясняющий приведение типов:

В чем разница между явным и неявное приведение типов?

0
ответ дан 7 November 2019 в 11:57
поделиться

Приведение () должно быть таким же; он выбрасывает InvalidCastException. Просто попробуйте это на C #:

 string t = "hello";
 object x = t;
 int j = (int) x;
-1
ответ дан 7 November 2019 в 11:57
поделиться

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

Это фактические эквиваленты:

double d = 10;
int i = (int)d;

Dim d As Double = 10
Dim i As Integer = d

Обратите внимание на опасность этой конструкции, когда вы просто присваиваете double целому числу в VB.NET , число с двойной точностью будет случайно уменьшено до целого числа.

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

Фактические эквиваленты:

// will not compile, cannot convert double to int

double d = 10;
int i = d; 

' will not compile, cannot convert double to int

Dim d As Double = 10
Dim i As Integer = DirectCast(d, Integer) 
{{1} }

[EDIT]

@Dan Tao:

Нет необходимости использовать DirectCast в C #, среда выполнения также предотвращает загрузку длинных значений в целые числа.Это то, что утверждает csauve, что C # не имеет DirectCast, что DirectCast может предотвратить присвоение различных типов переменных, тогда как «поскольку» C # не имеет этого DirectCast, он будет молча ошибаться при назначении различных типов. Но, как видите, это не так, приведение типов в C # в точности совпадает с DirectCast. Это вызовет ошибку времени выполнения InvalidCastException :

long l = 10;
object o = l;
int i = (int)o;

Это также вызовет ту же ошибку времени выполнения , как указано выше:

Dim l As Long = 10
Dim o As Object = l
Dim i As Integer = DirectCast(o, Integer)

Вот здесь и появляется «забавная» часть с VB .NET вам нужно запомнить много ключевых слов, чтобы чего-то добиться. В C #, если данное ключевое слово может быть использовано в другом сценарии (например, в этом понижающем преобразовании переменной), они не будут изобретать другое ключевое слово только для того, чтобы это произошло.

В C # вам просто нужно сделать следующее:

long l = 10;
object o = l;
int i = (int)(long)o;

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

 Dim l As Long = 10
 Dim o As Object = l
 Dim i As Integer = DirectCast(DirectCast(o, Long), Integer)

Но это не будет компилироваться, так как же добиться преобразования long в целое число? Вы должны помнить другие ключевые слова VB.NET. В то время как в C # он ортогонален, вы распаковываете переменную, используя эту конструкцию (введите здесь) , вы также понижаете / повышаете, используя ту же конструкцию (введите здесь) . В VB.NET существует фундаментальная пропасть между загрузкой значения из объекта и его понижением. Итак, в VB.NET вы должны сделать это:

 Dim l As Long = 10
 Dim o As Object = l
 Dim i As Integer = CType(o, Integer)

Хм ..Я думаю, что путаница csauve проистекает из многократного использования C # (введите здесь) , сначала он используется для понижающего преобразования; во-вторых, та же конструкция (проверьте первую часть этого сообщения, object o = l ) также используется для распаковки значения из объекта, который, будьте уверены, имеет безопасное поведение преобразования типа DirectCast, они одинаковы !

Это понижающее преобразование ...

long l = 1;
int i = (int) l;

... не эквивалентно:

Dim l As Long = 1
Dim i As Integer = DirectCast(l, Integer)

Если вы хотите выполнить понижающее преобразование, вы должны сделать следующее:

Dim l As Long = 1
Dim i As Integer = CInt(l) ' can also use CType

Теперь, если программист VB.NET программирует намеренно , а не сонный при кодировании, почему он будет использовать DirectCast, когда полностью осознает, что он не может назначать разные типы? Если программист VB.NET действительно хотел снизить уровень своей производительности, ему в первую очередь не следует пытаться использовать DirectCast. Теперь программист VB.NET, обнаружив, что DirectCast не может использоваться для понижающего преобразования, должен вернуть то, что он написал, и заменить его на CInt (или CType)

1
ответ дан 7 November 2019 в 11:57
поделиться

Вы действительно пытались запустить свой пример кода?

Что касается ...

//This code uses a type converter to go across an inheritance tree
string s = "10";
int i = (int)s;

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

0
ответ дан 7 November 2019 в 11:57
поделиться

ВТОРОЕ ОБНОВЛЕНИЕ :

Хорошо, вот метод C #, который был предложен для выполнения в основном того же, что DirectCast в VB.NET.

static T DirectCast<T>(object o) where T : class
{
    T value = o as T;
    if (value == null && o != null)
    {
        throw new InvalidCastException();
    }
    return value;
}

Вот проблемы с вышеупомянутым методом:

  1. Он имеет ограничение , где T: class , чего нет в DirectCast .
  2. Он упаковывает свой аргумент как System.Object - опять же, неверно для DirectCast (по крайней мере, я не знаю).
  3. Он использует как без необходимости (именно поэтому в первую очередь используется ограничение class ); вызов (T) o вызовет исключение InvalidCastException , если это не сработает; зачем проверять, совпадает ли значение, используя как , только для того, чтобы сгенерировать то же исключение, которое было бы сгенерировано, если бы вы сначала пошли по маршруту (T) o ?

Метод действительно можно было бы переписать для получения тех же результатов, что и DirectCast , следующим образом:

static T DirectCast<T>(object o) {
    return (T)o;
}

Забавное наблюдение: на самом деле все, что делает этот метод, - это упаковывает значение, а затем пытается его распаковать. Другими словами, DirectCast (12.0) действительно будет таким же, как (int) (object) 12.0 (и любой из них вызовет исключение). Понимание этого делает предлагаемый метод DirectCast совершенно ненужным.

Вот пример того, как DirectCast и приведение с помощью () «различаются» между VB.NET и C #:

VB:

Dim i As Integer = 12
Dim l As Long = DirectCast(i, Long) ' does not compile '

C #:

int i = 12;
long l = i; // DOES compile

Итак, один компилируется, а другой нет. Но посмотрите на этот код. В чем смысл DirectCast , когда вы уже знаете тип объекта? Это нереалистичное сравнение, потому что в VB.NET никогда не было бы причин для вызова DirectCast , как в приведенном выше коде. (Если вы хотите преобразовать значение , имеющее тип System.Int32 , в значение типа System.Int64 в VB.NET, вы должны использовать ] CLng , а не DirectCast .) Если бы там была переменная с типом System.Object , , тогда имело бы смысл использовать ] DirectCast , и приведенный ниже код действительно будет эквивалентен:

VB:

Dim i As Integer = 12
Dim o As Object = i
Dim l As Long = DirectCast(o, Long) ' compiles, throws an exception '

C #:

int i = 12;
object o = i;
long l = (long)o; // compiles, throws an exception

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


РЕДАКТИРОВАТЬ : Мне жаль, что я опубликовал код VB, который не компилировался. Пересмотрев сказанное, я снимаю свой второй ответ, но сохраняю первый.

Если вы имеете в виду использование DirectCast , в котором вы берете объект неизвестного типа и пытаетесь привести его к желаемому типу, то он такой же, как C #. () cast:

VB:

Dim o As Object = SomeObject()
Dim i As Integer = DirectCast(o, Integer)

C #:

object o = SomeObject();
int i = (int)o;

Это потому, что, если o типизирован как System.Object , то () Операция в C # попытается распаковать его. Это не удастся, если типы не совпадают в точности; например, если o - это System.Double в штучной упаковке, то (int) o вызовет исключение, потому что o должно ] нужно распаковать как System.Double , прежде чем его можно будет преобразовать в System.Int32 (если вы мне не верите, попробуйте сами!).


Примечание: приведенное ниже сообщение неверно, поскольку DirectCast не не выполняет расширяющие преобразования; в любом случае оставляю это потомкам.

С другой стороны, при работе с расширяющими и сужающими преобразованиями использование операции () в C # делает больше работы, чем простое приведение, как вы указали (т. Е. Вы можете сделать (int) someDouble ). В этом сценарии DirectCast эквивалентно простому старому назначению в C #:

VB:

Dim i As Integer = 12
Dim l As Long = DirectCast(i, Long) ' does not compile, actually '

C #:

int i = 12;
long l = i;
8
ответ дан 7 November 2019 в 11:57
поделиться

Я думаю, этот сценарий лучше всего объясняет, почему DirectCast имеет ложное представление о безопасности проверки типов во время компиляции для типов, не являющихся объектами (ключевое слово объекта), и просто предназначен для возврата на место.

float f = 10;
long l = f;

Option Strict On    
Dim f As Single = 10
Dim l As Long = f

Кодировщик C #, обнаружив, что float не может быть напрямую назначен long и не будет компилироваться, сделает следующее:

long l = (long)f;

Что правильно.

Теперь давайте обратимся к нашему кодировщику VB.NET, обнаружив, что float не может быть назначен на long и не будет компилироваться, попробуем следующее:

Dim l As Long = DirectCast(f, Long)

Через несколько секунд ...

Программист VB.Net : «Пожалуйста, позвольте мне сделать то, что я предлагаю, пожалуйста, скомпилируйте, пожалуйста ... !!!»

После нескольких секунд просмотра в Google и MSDN:

Программист VB.NET: «А ... так что у меня есть использовать эту конструкцию CLng или CType для приведения переменных »

Dim l As Long = CLng(f)

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

Насколько полезен DirectCast в этом сценарии, если он все-таки не будет использоваться?


[EDIT]

@Jules

Я не утверждаю, что все программисты VB.NET не знают, как на самом деле использовать DirectCast, некоторые из них действительно знают, что DirectCast предназначен только для использования с объектами только типы (и примитивные типы, заключенные в объект).

Один из сценариев, при котором кодировщик VB.NET, перекодирующий существующий код C # в VB.NET, придет к неверному выводу, связан с ожидаемой (правильной или неправильной) симметрией языков по отношению друг к другу.

Когда он видит в коде эту конструкцию ...

TextBox txt = (TextBox)sender;

... Он переведет это на следующее:

Dim txt As TextBox = DirectCast(sender, TextBox)

Что правильно.

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

/* numbers are stored in file as float(component's file structure 
is designed by 3rd party company) */
float f = file.ReadFloat(0); 
long l = (long)f; // but we don't care about using the fractional part

... в этот:

Dim f As Single = file.ReadFloat(0)
Dim l As Long = DirectCast(f, Long)

Если Человек C # - это тот, кто конвертирует код C # в VB.NET, он будет разочарован очевидным отсутствием симметрии здесь.

Но для человека VB.NET, которому поручено преобразовать код C # в VB.NET, у него сложится впечатление, что компилятор C # не улавливает несовместимые присвоения типов, в то время как VB.NET улавливает его. Теперь, за это очевидное открытие, я хвастаюсь этой особенностью VB.NET перед своими коллегами и на некоторых форумах.

Но чтобы программист VB.NET не совершил ошибку, неправильно сделав вывод о назначении первого кода.Фрагмент кода C # выше начал свою жизнь так изначально был написан так:

float f = file.ReadFloat(0); 
long l = f; 

И он не будет компилироваться, компилятор C # улавливает несовместимые присвоения типов в том же духе, что и эквивалентный VB.NET с Option Strict On также не будет компилироваться (хотя и не будет компилироваться только тогда, когда для Option Strict установлено значение On , слишком мягко). Поэтому нам нужно привести тип float к long, используя (long) . Становится следующим: long l = (long) f;

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

TextBox txt = (TextBox)sender;

... в этот код:

Dim txt As TextBox = DirectCast(sender, Textbox)

Мы должны преобразовать этот код ...

long l = (long)f; // will compile

... в этот код:

Dim l As Long = DirectCast(f, Long) ' will not compile

Но, увы, он не будет компилироваться при преобразовании между совместимыми примитивными типами, вот где DirectCast не справляется. t предлагает какую-либо симметрию по отношению к приведенному выше коду C #, его нельзя использовать для преобразования совместимых примитивных типов, несмотря на его название Direct Cast .

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

Или, как мне кажется, конструкция DirectCast должна быть изменена, чтобы она могла приводить совместимые типы, как старые и новые языки с тех пор, например C, C ++, C #, Java, Delphi, D и т. Д. Делая это, он обеспечит значительную симметрию VB.NET с другими языками, когда дело доходит до приведения типов. Сделав это, мы также можем выбросить (только гипотетически, мы не можем заставить отказывать другие программы, которые полагаются на старые функции)все множество функций, имена которых не сопоставляются напрямую с их типами (например, CInt, CDbl, CSng и т. д.), мы просто будем использовать DirectCast вместо них.

0
ответ дан 7 November 2019 в 11:57
поделиться
Другие вопросы по тегам:

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