Как я понимаю, нет способа реализовать это только в C #, потому что строковые литералы всегда System.String
s, а система типов C # полностью игнорирует размеры массивов.
Предполагая, что вы используете пользовательский тип значения (и да, вы должны объявить 10 char
полей, потому что char[10]
будет храниться в куче),
struct String10
{
char c0;
char c1;
...
char c9;
public String10(string literal){...}
}
Вы можете написать инструмент (в качестве шага после компиляции), который проходит через IL и отклоняет каждый вызов этого конструктора String10
, который не имеет допустимой (т. Е. Не более 10 символов) строки литерал в качестве параметра.
new String10("0123456789") //valid
new String10("0123456789A") //rejected
new String10(someString) //has to be rejected as well → undecidable ↔ halting problem
Если вам не нравится писать new String10(...)
, вы можете вместо этого определить неявное преобразование из System.String
в String10
. Под капотом это будет статический метод, вызываемый компилятором C # вместо вас.
Одна библиотека, которая позволяет вам смотреть на IL, - это mono.cecil .
Вы получите новый тип данных, отличный от System.String
. Вы можете переопределить метод ToString
, чтобы String10
можно было использовать в String.Format
и в друзьях, вы даже можете определить расширяющее (неявное) преобразование в System.String
, чтобы вы могли использовать String10
с API, ожидающими System.String
.