Intereting Posts
Инъекция зависимостей в WebAPI с замком Виндзор Код структуры Entity Framework Первые соглашения об именах – назад к именам множественных таблиц? ТипDescriptor.GetProperties () vs Type.GetProperties () String.Format (“{0: C2}”, -1234) (формат валюты) обрабатывает отрицательные числа как положительные Вызвать C # DLL из Inno Setup с помощью обратного вызова Есть функция, которая возвращает индекс, где начинается соответствие RegEx? Рисование движущейся линии в прозрачной панели в C # Совместное использование переменных c # между методами? Идентифицировать объекты IDisposable Как получить список доступных методов в веб-службе WebAPI? RSACryptoServiceProvider инициализирует собственный открытый ключ и закрытый ключ установка пакета nuget «тот же ключ уже добавлен». Почему свойства зависимостей в WPF должны быть статическими Добавить свойство в анонимный тип после создания C # и неизменяемость и поля только для чтения … ложь?

C # Char из Int, используемый как String – реальный эквивалент VB Chr ()

Я преобразовал макрос VBA в C #. А в VBA chr(7) можно просто конкатенировать string как если бы chr() выдавал string . Почему это невозможно сделать на C #?

Я пытаюсь найти ясный ответ на свой вопрос. Я прочитал много сообщений и связанных с ними вопросов по этому вопросу на SO и нескольких других сайтах. Например, это ключевой ответ (многие другие отмечены как дубликаты и redirect на этот): что эквивалентно функциям VB Asc () и Chr () в C #?

И, к сожалению, ответ не ясен, и много раз они заявляют, что это правильное использование:

 string mystring=(char)7; 

Тем не менее, это дает мне ошибку компилятора, поскольку она не оценивается как строка.

Я должен был использовать это, чтобы заставить его работать:

 string mystring=((char)7).ToString(); 

Это будет эквивалентно функции VB Chr (), так как Chr () в VB оценивается как строка.

Мой вопрос заключается в следующем: всегда ли мне нужно явно char в string или есть случаи, когда он преобразуется неявно?

ОБНОВИТЬ:

Ответ Per @ Dirk, это также работает:

 string mystring = "" + (char)7; 

Это не уменьшает мою тайну. Если конкатенация работает, почему нет неявного литья?

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

Вы открываете коробку Пандоры с этим вопросом. Chr () является устаревшей функцией в VB.NET, любой современный код должен использовать ChrW (). Разница заключается в том, как интерпретировать значение символа, ChrW () предполагает, что код символа Unicode (W = wide). Chr () откатывает часы в предыдущем столетии, каменный век без Unicode, где символы были либо в наборе символов ASCII (0..127), либо в виде расширенного символа (128..255). Если расширенные символы принадлежат кодовой странице . Было использовано много разных кодовых страниц. Очень значительная катастрофа, программы не могли правильно интерпретировать текст, который был сгенерирован другой машиной, расположенной в другой стране. Или даже в одной и той же стране Япония использовала несколько кодовых страниц, в которых ни одна из них не доминировала. Изготовление моджибака .

Я предполагаю, что вы имеете в виду ChrW (), никто не любит моджибаке. Не C #. Использование Char.ToString () в порядке, альтернативой является использование конструктора строк, который принимает char :

  string mystring = new string((char)7, 1); 

Или более общую форму, которую вы можете предпочесть:

  public static string ChrW(int code) { return new string((char)code, 1); } 

Не единственный способ сделать это, использование литералов также возможно и, вероятно, будет тем, что вы предпочитаете по вспомогательному методу. И основная причина, по которой C # не нуждается в вспомогательной функции, такой как Chr (). Управляющий код ASCII 7 является символом колокола, он берет вас, когда вы пишете его на консоли, вы можете использовать escape для этого:

  string mystring = "\a"; 

Не совсем незабываемо, это происходит от Unix. Другими являются «\ b» для backspace, «\ t» для вкладки «\ r» для возврата каретки и «\ n» для фида строки. Классический трюк для стирания последнего типизированного символа в окне консоли – Console.Write("\b \b"); , Следует отметить свойство Environment.NewLine . Это примерно так, как вы должны нажать его с контрольными символами.

И последнее, но не менее важное: \ U и \ u спецификатор, который позволяет кодировать любого символа:

  string mystring = "\u0007"; 

Непонятно из примера, но значение \ u должно быть шестнадцатеричным. \ U необходимо при использовании кодовых точек из верхних бит-бит в Юникоде.

Если вам абсолютно необходимо использовать метод Chr по причинам, связанным с наследством, лучше всего использовать его как обычный метод .

Если вы не хотите импортировать VisualBasic или хотите увидеть, как это работает, Reflector дает хороший fragment кода:

 public static char Chr(int CharCode) { char ch; if ((CharCode < -32768) || (CharCode > 0xffff)) { throw new ArgumentException(Utils.GetResourceString("Argument_RangeTwoBytes1", new string[] { "CharCode" })); } if ((CharCode >= 0) && (CharCode < = 0x7f)) { return Convert.ToChar(CharCode); } try { int num; Encoding encoding = Encoding.GetEncoding(Utils.GetLocaleCodePage()); if (encoding.IsSingleByte && ((CharCode < 0) || (CharCode > 0xff))) { throw ExceptionUtils.VbMakeException(5); } char[] chars = new char[2]; byte[] bytes = new byte[2]; Decoder decoder = encoding.GetDecoder(); if ((CharCode >= 0) && (CharCode < = 0xff)) { bytes[0] = (byte) (CharCode & 0xff); num = decoder.GetChars(bytes, 0, 1, chars, 0); } else { bytes[0] = (byte) ((CharCode & 0xff00) >> 8); bytes[1] = (byte) (CharCode & 0xff); num = decoder.GetChars(bytes, 0, 2, chars, 0); } ch = chars[0]; } catch (Exception exception) { throw exception; } return ch; } 

Для символа ASCII он просто вызывает Convert.ToChar , что эквивалентно (char)CharCode . Первая интересная вещь – вызов Utils.GetLocaleCodePage :

 internal static int GetLocaleCodePage() { return Thread.CurrentThread.CurrentCulture.TextInfo.ANSICodePage; } 

Хотя можно ожидать, что он будет таким же, как Encoding.Default , он создает кодировку, связанную с культурой текущего streamа, а не с системой. Остальное просто набивает код в массив и использует кодировку для его декодирования.

Этот метод имеет одно основное предостережение, как обычно при работе с кодировкой, – оно сильно зависит от текущей локали, а изменение культуры текущего streamа прерывает все преобразования для кодов вне ASCII. Но все же, если это то, что вы хотите сделать, вот приблизительный и короткий эквивалент:

 public static char Chr(int code) { var encoding = Encoding.GetEncoding(Thread.CurrentThread.CurrentCulture.TextInfo.ANSICodePage); return encoding.GetChars(BitConverter.GetBytes((ushort)code))[0]; } 

В этом не хватает некоторых проверок исходного метода, особенно проверки по одному байту и диапазону.

Тогда в VB.NET есть намного более простой и лучший метод – ChrW для Unicode:

 public static char ChrW(int CharCode) { if ((CharCode < -32768) || (CharCode > 0xffff)) { throw new ArgumentException(Utils.GetResourceString("Argument_RangeTwoBytes1", new string[] { "CharCode" })); } return Convert.ToChar((int) (CharCode & 0xffff)); } 

Это снова возвращается к ToChar :

 public static char ToChar(int value) { if ((value < 0) || (value > 0xffff)) { throw new OverflowException(Environment.GetResourceString("Overflow_Char")); } return (char) value; } 

Как вы можете видеть, ChrW точно так же, как простое преобразование старого charкроме отрицательных значений! Вы знаете, хотя код символа должен вписываться в два байта, он, возможно, исходил как из подписанного, так и из unsigned short, поэтому метод гарантирует, что это правильный номер для обоих типов происхождения. Если вы хотите принять это во внимание, просто сделайте CharCode & 0xffff .

Итак, как вы можете видеть, Chr – это просто Encoding.GetChars где кодировка – это stream текущего streamа, а ChrW – это просто (char)CharCode , за исключением того, что обе функции также обрабатывают отрицательные значения. Другого разницы нет.


Что касается исходной части вашего вопроса, вы не можете преобразовать из char в string потому что … нет возможного преобразования. Они не наследуют друг друга, поэтому вы не можете их отличать, и у них нет пользовательских операторов преобразования, а string не является примитивным типом значений, поэтому нет встроенного преобразования. VB.NET может позволить вам сделать это, но в целом, это позволяет гораздо хуже, благодаря своим древним версиям.

TL; DR Is (char) эквивалентно Chr ? Только для символьного кода ASCII (от 0 до 127), в противном случае нет . И Chr перестает работать, если текущая кодировка и кодировка кода различаются, что имеет значение, если вы используете символы, отличные от ASCII.

Просто для упрощения синтаксиса. Следующий class AChar обрабатывает преобразования.

 string A = (AChar)65; Console.WriteLine(A); // output is "A" 

Следующий class представляет символ и определяет преобразования с кодовой страницы ASCII:

 struct AChar { public static implicit operator AChar(char value) => new AChar { Value = value }; public static explicit operator AChar(string value) { if (string.IsNullOrEmpty(value)) return '\x0000'; if (value.Length > 1) throw new InvalidCastException("String contains more than 1 character."); return value[0]; } public static explicit operator AChar(long value) { if(value < 0 || value > 0xFF) throw new InvalidCastException("Char code is out of ASCII range."); return (AChar)Encoding.ASCII.GetString(new[] { (byte)value }); } public static implicit operator AChar(byte value) => (AChar)(long)value; public static explicit operator AChar(int value) => (AChar)(long)value; public static implicit operator char(AChar aChar) => aChar.Value; public static implicit operator string(AChar aChar) => aChar.Value.ToString(); public static bool operator==(AChar left, AChar right) => left.Value == right.Value; public static bool operator!=(AChar left, AChar right) => left.Value != right.Value; public static bool operator >(AChar left, AChar right) => left.Value > right.Value; public static bool operator >=(AChar left, AChar right) => left.Value >= right.Value; public static bool operator < (AChar left, AChar right) => left.Value < right.Value; public static bool operator <=(AChar left, AChar right) => left.Value < = right.Value; public override string ToString() => this; public override int GetHashCode() => Value.GetHashCode(); public override bool Equals(object obj) => obj is AChar && ((AChar)obj).Value == Value; char Value { get; set; } } 

Сначала преобразуйте код символа в AChar, он совместим с string и string C #.

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

 string mystring = "" + (char)7; 

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