Мне понравился ответ из @Mahomedalid
, кроме этого факта, сообщенного в комментарии от @Bill Karwin
. Возможная проблема, поднятая @Jan Koritak
, верна. Я столкнулся с этим, но я нашел для этого трюк и просто хочу поделиться ею здесь, для тех, кто сталкивается с проблемой.
мы можем заменить функцию REPLACE предложением where в подзапросе инструкции «Подготовить»:
Использование моей таблицы и имени столбца
SET @SQL = CONCAT('SELECT ', (SELECT GROUP_CONCAT(COLUMN_NAME) FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'users' AND COLUMN_NAME NOT IN ('id')), ' FROM users');
PREPARE stmt1 FROM @SQL;
EXECUTE stmt1;
Итак, это исключает только поле id
, но не company_id
Надеюсь, это поможет любому, кто ищет решение.
С уважением
Кроме очевидной разницы [1 129]
const
значения VS readonly
могут быть вычислены динамично, но потребность, которая будет присвоена перед выходами конструктора.. после этого это замораживается. static
. Вы используете ClassName.ConstantName
нотация для доступа к ним. существует тонкое различие. Считайте класс определенным в AssemblyA
.
public class Const_V_Readonly
{
public const int I_CONST_VALUE = 2;
public readonly int I_RO_VALUE;
public Const_V_Readonly()
{
I_RO_VALUE = 3;
}
}
AssemblyB
ссылки AssemblyA
и использование эти значения в коде. Когда это компилируется,
const
значение, оно похоже на находить-замену, значение 2 'испеклось в' AssemblyB
IL. Это означает это, если завтра я обновлю I_CONST_VALUE
к 20 в будущем. AssemblyB
все еще имел бы 2, пока я не перекомпилировал его . readonly
значение, это похоже ref
к ячейке памяти. Значение не испеклось в [1 116] IL. Это означает, что, если ячейка памяти обновляется, AssemblyB
, получает новое значение без перекомпиляции. Таким образом, если I_RO_VALUE
обновляется к 30, только необходимо создать AssemblyA
. Все клиенты не должны быть перекомпилированы. Поэтому, если Вы уверены, что значение константы не изменится, используют const
.
public const int CM_IN_A_METER = 100;
, Но если у Вас есть константа, которая может измениться (например, w.r.t. точность).. или когда в сомнении, используйте readonly
.
public readonly float PI = 3.14;
Обновление: Aku должен получить упоминание, потому что он указал на это сначала. Также я должен включиться, где я изучил это.. Эффективный C# - Bill Wagner
Основное отличие - то, что Константа является эквивалентом C #DEFINE. Число буквально получает предварительный компилятор крыла, которым заменяют. Только для чтения на самом деле рассматривается как переменную.
Это различие особенно релевантно, когда у Вас есть Проект A в зависимости от Общедоступной константы из Проекта B. Предположим общедоступные постоянные изменения. Теперь Ваш выбор константы / только для чтения повлияет на поведение на проект A:
Константа: проект A не ловит новое значение (если это не перекомпилировано с новой константой, конечно), потому что это было скомпилировано с константами, в которых заменяют.
ReadOnly: Проект A будет всегда спрашивать проект B, поскольку это - значение переменной, таким образом, это возьмет новое значение общедоступной константы в B.
Честно, я рекомендовал бы использовать только для чтения для почти всего кроме действительно универсальных констант (например, Пи, Inches_To_Centimeters). Для чего-либо, что могло возможно измениться, я говорю использование, только для чтения.
Hope это помогает, Alan.
Одна вещь добавить к тому, что люди сказали выше. Если у Вас есть блок, содержащий значение только для чтения (например, MaxFooCount только для чтения = 4;), можно изменить значение, которое вызов блоков видит путем поставки новой версии того блока с различным значением (например, MaxFooCount только для чтения = 5;)
, Но с константой, это было бы свернуто в код вызывающей стороны, когда вызывающая сторона была скомпилирована.
при достижении этого уровня мастерства C# Вы готовы к книге Bill Wagner, Эффективному C#: 50 Особенных методов Улучшить Ваш C#, Который отвечает на этот вопрос подробно, (и 49 других вещей).
Другой глюк .
, Так как константа действительно только работает с типами основных данных, если Вы хотите работать с классом, можно чувствовать себя "вынужденными" использовать ReadOnly. Однако остерегайтесь прерывания! ReadOnly подразумевает, что Вы не можете заменить объект другим объектом (Вы не можете заставить его относиться к другому объекту). Но любой процесс, который имеет ссылку на объект, является бесплатным изменить значения внутренний объект!
Так не перепутаны в размышление, что ReadOnly подразумевает, что пользователь не может изменить вещи. Нет никакого простого синтаксиса в C# для препятствования инстанцированию класса изменение его внутренних значений (насколько я знаю).
Они являются оба постоянными, но константа доступна также во время компиляции. Это означает, что один аспект различия - то, что можно использовать переменные константы в качестве входа для приписывания конструкторов, но не переменных только для чтения.
Пример:
public static class Text {
public const string ConstDescription = "This can be used.";
public readonly static string ReadonlyDescription = "Cannot be used.";
}
public class Foo
{
[Description(Text.ConstDescription)]
public int BarThatBuilds {
{ get; set; }
}
[Description(Text.ReadOnlyDescription)]
public int BarThatDoesNotBuild {
{ get; set; }
}
}
Существует глюк с consts! При ссылке на константу от другого блока его значение будет скомпилировано прямо в блок вызова. Тот путь при обновлении константы в блоке, на который ссылаются, это не изменится в блоке вызова!
Только для добавления ReadOnly для ссылочных типов только делает ссылку, только для чтения не значения. Например:
public class Const_V_Readonly
{
public const int I_CONST_VALUE = 2;
public readonly char[] I_RO_VALUE = new Char[]{'a', 'b', 'c'};
public UpdateReadonly()
{
I_RO_VALUE[0] = 'V'; //perfectly legal and will update the value
I_RO_VALUE = new char[]{'V'}; //will cause compiler error
}
}
Это объясняет его . Сводка: константа должна быть инициализирована во время объявления, только для чтения может быть инициализирован на конструкторе (и таким образом иметь различное значение в зависимости от используемого конструктора).
РЕДАКТИРОВАНИЕ: Посмотрите глюк Gishu выше для тонкого различия
Отмеченная константа переменных немного больше, чем #define макросы со строгим контролем типов, во время компиляции ссылки на переменную константы заменяются встроенными литеральными значениями. Как следствие только определенные встроенные примитивные типы значения могут использоваться таким образом. Переменные, отмеченные только для чтения, могут быть установлены, в конструкторе, во времени выполнения, и их только для чтения осуществляется во время времени выполнения также. Существует некоторая незначительная стоимость производительности, связанная с этим, но это означает, что можно использовать только для чтения с любым типом (даже ссылочные типы).
кроме того, переменные константы по сути статичны, тогда как переменные только для чтения могут быть экземпляром, конкретным при желании.
Существует маленький глюк с только для чтения. Поле только для чтения может быть установлено многократно в конструкторе (конструкторах). Даже если значение установлено в двух различных цепочечных конструкторах, оно все еще позволяется.
public class Sample {
private readonly string ro;
public Sample() {
ro = "set";
}
public Sample(string value) : this() {
ro = value; // this works even though it was set in the no-arg ctor
}
}
Я верю const
, значение является тем же для всех объектов (и должен быть инициализирован с литералом), тогда как readonly
может отличаться для каждого инстанцирования...
Один из членов команды в нашем офисе обеспечил следующее руководство на том, когда использовать константу, статичную, и только для чтения:
Одно заключительное примечание: поле константы статично, но инверсия не верна.
Константа является временем компиляции, постоянным, тогда как только для чтения позволяет значению быть вычисленным во времени выполнения и наборе в полевом инициализаторе или конструкторе. Так, 'константа' является всегда постоянной, но 'только для чтения' только для чтения, как только она присвоена.
у Eric Lippert из команд C# есть больше информации о различных типах неизменности
Вот другая ссылка демонстрация, как константа не является безопасной версией, или важной для ссылочных типов.
Сводка :
В основном; вы можете присвоить значение статическому полю только для чтения непостоянному значению во время выполнения, тогда как константе нужно присвоить постоянное значение.
Константа будет скомпилирована в потребителя как буквальное значение, а статическая строка будет служить ссылкой на определенное значение.
В качестве упражнения попробуйте создать внешнюю библиотеку и использовать его в консольном приложении, затем измените значения в библиотеке и перекомпилируйте ее (без перекомпиляции программы-потребителя), поместите DLL в каталог и запустите EXE вручную, вы должны обнаружить, что постоянная строка не изменяется.
Еще одна проблема: значения, доступные только для чтения, могут быть изменены «коварным» кодом через отражение.
var fi = this.GetType()
.BaseType
.GetField("_someField",
BindingFlags.Instance | BindingFlags.NonPublic);
fi.SetValue(this, 1);
Могу ли я изменить частное унаследованное поле только для чтения в C # с помощью отражения?