Как ограничить значение переменной в c
Перейти к содержимому

Как ограничить значение переменной в c

  • автор:

Пределы целых чисел в C и C++

Ограничения для целочисленных типов в C и C++ представлены в следующей таблице. Эти ограничения заданы в стандартном файле заголовка C . Стандартный файл заголовка C++ содержит , который включает в себя .

В Microsoft C также допускается объявление целочисленных переменных с указанием размера, которые относятся к целочисленным типам с размером 8, 16, 32 или 64 бит. Дополнительные сведения о них см. в статье Целочисленные типы с указанием размера.

Ограничения для целочисленных констант

Константа Значение Значение
CHAR_BIT Количество битов в наименьшей переменной, которая не является битовым полем. 8
SCHAR_MIN Минимальное значение для переменной типа signed char . –128
SCHAR_MAX Максимальное значение для переменной типа signed char . 127
UCHAR_MAX Максимальное значение для переменной типа unsigned char . 255 (0xff)
CHAR_MIN Минимальное значение для переменной типа char . –128 (или 0, если используется параметр /J)
CHAR_MAX Максимальное значение для переменной типа char . –127 (или 255, если используется параметр /J)
MB_LEN_MAX Максимальное число байтов в многобайтовом символе. 5
SHRT_MIN Минимальное значение для переменной типа short . -32768
SHRT_MAX Максимальное значение для переменной типа short . 32767
USHRT_MAX Максимальное значение для переменной типа unsigned short . 65 535 (0xffff)
INT_MIN Минимальное значение для переменной типа int . -2147483647 — 1
INT_MAX Максимальное значение для переменной типа int . 2147483647
UINT_MAX Максимальное значение для переменной типа unsigned int . 4 294 967 295 (0xffffffff)
LONG_MIN Минимальное значение для переменной типа long . -2147483647 — 1
LONG_MAX Максимальное значение для переменной типа long . 2147483647
ULONG_MAX Максимальное значение для переменной типа unsigned long . 4 294 967 295 (0xffffffff)
LLONG_MIN Минимальное значение для переменной типа long long . –9 223 372 036 854 775 807 – 1
LLONG_MAX Максимальное значение для переменной типа long long . 9 223 372 036 854 775 807
ULLONG_MAX Максимальное значение для переменной типа unsigned long long . 18 446 744 073 709 551 615 (0xffffffffffffffff)

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

Завершение блока, относящегося только к системам Майкрософт

Ограничения параметров типа (руководство по программированию на C#)

Ограничения сообщают компилятору о характеристиках, которые должен иметь аргумент типа. Без ограничений аргумент типа может быть любым типом. Компилятор может только предполагать членов System.Object, который является главным базовым классом для всех типов .NET. Дополнительные сведения см. в статье Зачем использовать ограничения. Если клиентский код использует тип, который не удовлетворяет ограничению, компилятор выдает ошибку. Ограничения задаются с помощью контекстного ключевого слова where . В следующей таблице описываются различные типы ограничений:

Ограничение Description
where T : struct Аргумент типа должен быть ненулевым типом значения, который включает record struct типы. См. дополнительные сведения о типах значений, допускающих значение NULL. Так как все типы значений имеют конструктор без параметров, объявленный или неявный, struct ограничение подразумевает new() ограничение и не может сочетаться с ограничением new() . Ограничение struct нельзя использовать вместе с ограничением unmanaged .
where T : class Аргумент типа должен быть ссылочным типом. Это ограничение также применяется к любому типу класса, интерфейса, делегата или массива. В контексте, допускающем значение NULL, должен быть ссылочным типом, T не допускаемым значением NULL.
where T : class? Аргумент типа должен быть ссылочным типом, допускающим значения NULL или не допускающим значения NULL. Это ограничение применяется также к любому классу, интерфейсу, делегату или типу массива, включая записи.
where T : notnull Аргумент типа должен быть типом, не допускающим значения NULL. Аргумент может быть ненулевым ссылочным типом или типом значения, не допускающего значение NULL.
where T : unmanaged Аргумент типа должен быть неуправляемым типом, не допускающим значения NULL. Ограничение unmanaged подразумевает ограничение struct и не может использоваться совместно с ограничением struct или new() .
where T : new() Аргумент типа должен иметь общий конструктор без параметров. При одновременном использовании нескольких ограничений последним должно указываться ограничение new() . Ограничение new() не может использоваться с ограничениями struct и unmanaged .
where T :

Аргумент типа должен иметь базовый класс или производный от него класс. В контексте, допускающем значение NULL, должен быть ссылочным типом, T не допускаемым значением NULL, производным от указанного базового класса.
where T : базового класса? Аргумент типа должен иметь базовый класс или производный от него класс. В контексте, допускающем значение NULL, T может быть либо типом, допускаемым null, либо не допускаемым значением NULL, производным от указанного базового класса.
where T :

Аргумент типа должен являться заданным интерфейсом или реализовывать его. Можно указать несколько ограничений интерфейса. Заданный в ограничении интерфейс также может быть универсальным. В контексте, допускающем значение NULL, должен быть ненулевой тип, T реализующий указанный интерфейс.
where T : интерфейса? Аргумент типа должен являться заданным интерфейсом или реализовывать его. Можно указать несколько ограничений интерфейса. Заданный в ограничении интерфейс также может быть универсальным. В контексте, допускающем значение NULL, может быть ссылочным типом, T не допускаемым значением NULL, или типом значения. T не может быть типом значений, допускаемым значением NULL.
where T : U Аргумент типа, указанный для T , должен быть аргументом, указанным для U , или производным от него. В контексте, допускающем значение NULL, если U это ненулевой ссылочный тип, T должен быть ненулевой ссылочный тип. Если U это ссылочный тип, допускающий значение NULL, T может иметь значение NULL или не допускающее значение NULL.
where T : default Это ограничение устраняет неоднозначность, если необходимо указать неограниченный параметр типа, переопределяя метод или указывая явную реализацию интерфейса. Ограничение default подразумевает базовый метод без ограничения class или struct . Дополнительные сведения см. в разделе характеристик ограничения default .

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

  • Вы можете применить не более одного из ограничений struct , и notnull class class? unmanaged ,. Если вы предоставляете любой из этих ограничений, это должно быть первое ограничение, указанное для этого параметра типа.
  • Ограничение базового класса ( where T : Base или) не может быть объединено с какими-либо ограничениями struct , , class или class? notnull unmanaged . where T : Base?
  • Можно применить не более одного ограничения базового класса в любой форме. Если вы хотите поддерживать базовый тип, допускающий значение NULL, используйте Base? .
  • Нельзя назвать как ненулевой, так и null-форму интерфейса в качестве ограничения.
  • Ограничение new() нельзя использовать с ограничением struct или unmanaged . Если указать new() ограничение, это должно быть последнее ограничение для этого параметра типа.
  • Ограничение default может применяться только к переопределениям или явным реализациям интерфейса. Его нельзя объединить с struct ограничениями или class ограничениями.

Зачем использовать ограничения

Ограничения определяют возможности и ожидания параметра типа. Объявление этих ограничений означает, что можно использовать операции и вызовы методов ограничивающего типа. Ограничения применяются к параметру типа, когда универсальный класс или метод использует любую операцию с универсальными элементами за пределами простого назначения, которая включает вызов любых методов, не поддерживаемых System.Object. Например, ограничение базового класса сообщает компилятору, что только объекты этого типа или производные от этого типа могут заменить этот аргумент типа. Имея такую гарантию, компилятор может вызывать методы указанного типа в универсальном классе. В следующем примере кода показаны функциональные возможности, которые можно добавить в класс GenericList (см. раздел Введение в универсальные шаблоны), применив ограничение базового класса.

public class Employee < public Employee(string name, int id) =>(Name, ID) = (name, id); public string Name < get; set; >public int ID < get; set; >> public class GenericList where T : Employee < private class Node < public Node(T t) =>(Next, Data) = (null, t); public Node? Next < get; set; >public T Data < get; set; >> private Node? head; public void AddHead(T t) < Node n = new Node(t) < Next = head >; head = n; > public IEnumerator GetEnumerator() < Node? current = head; while (current != null) < yield return current.Data; current = current.Next; >> public T? FindFirstOccurrence(string s) < Node? current = head; T? t = null; while (current != null) < //The constraint enables access to the Name property. if (current.Data.Name == s) < t = current.Data; break; >else < current = current.Next; >> return t; > > 

Это ограничение позволяет универсальному классу использовать свойство Employee.Name . Ограничение указывает, что все элементы типа T гарантированно являются либо объектом Employee , либо объектом, который наследует от Employee .

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

class EmployeeList where T : Employee, System.Collections.Generic.IList, IDisposable, new() < // . >

При применении where T : class ограничения избегайте == операторов и != параметров типа, так как эти операторы проверяют только эталонное удостоверение, а не на равенство значений. Такое поведение будет наблюдаться даже в том случае, если эти операторы будут перегружены в типе, используемом в качестве аргумента. Эта особенность показана в следующем коде, который будет возвращать значение false даже в том случае, если класс String перегружает оператор == .

public static void OpEqualsTest(T s, T t) where T : class < System.Console.WriteLine(s == t); >private static void TestStringEquality() < string s1 = "target"; System.Text.StringBuilder sb = new System.Text.StringBuilder("target"); string s2 = sb.ToString(); OpEqualsTest(s1, s2); > 

Компилятору известно только то, что T является ссылочным типом во время компиляции, и он должен использовать операторы по умолчанию, которые действительны для всех ссылочных типов. Если необходимо проверить равенство значений, примените where T : IEquatable или where T : IComparable ограничение и реализуйте интерфейс в любом классе, используемом для создания универсального класса.

Ограничение нескольких параметров

Ограничения можно применить к нескольким параметрам. Кроме того, к одному параметру можно применять несколько ограничений, как показано в следующем примере:

class Base < >class Test where U : struct where T : Base, new()

Несвязанные параметры типа

Не имеющие ограничений параметры типа (например, T в общем классе SampleClass<> ) называются несвязанными. В отношении несвязанных параметров типа применяются следующие правила:

  • Нельзя != использовать операторы == , так как не гарантируется, что аргумент конкретного типа поддерживает эти операторы.
  • Их можно преобразовать в System.Object или явно преобразовать в любой тип интерфейса.
  • Можно сравнить их со значением null. Если несвязанный параметр сравнивается null , сравнение всегда возвращает значение false, если аргумент типа является типом значения.

Параметры типа в качестве ограничений

Использование параметров универсального типа в качестве ограничений применимо, когда функция-член со своим параметром типа должна ограничивать этот параметр параметром содержащего типа, как показано в следующем примере:

public class List < public void Add(List items) where U : T > 

В предыдущем примере T является ограничением типа в контексте метода Add и несвязанным параметром типа в контексте класса List .

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

//Type parameter V is used as a type constraint. public class SampleClass where T : V

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

Ограничение notnull

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

Ограничение notnull действует только при использовании в контексте, допускающем значения NULL. При добавлении ограничения notnull в очевидный контекст, допускающий значения NULL, компилятор не создает никаких предупреждений или ошибок в случае нарушений ограничения.

Ограничение class

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

Ограничение default

Добавление ссылочных типов, допускающих значения NULL, усложняет использование T? для универсального типа или метода. T? можно использовать либо с ограничением struct class , но один из них должен присутствовать. Если используется ограничение class , T? ссылается на ссылочный тип, допускающий значения NULL, для T . T? можно использовать, если ни в коем случае не применяется ограничение. В этом случае T? интерпретируется как T? для типов значений и ссылочных типов. Но если T — экземпляр Nullable , T? соответствует T . Другими словами, это ограничение не станет T?? .

Так как T? теперь можно использовать без ограничения class или struct , в переопределениях или явных реализациях интерфейса могут возникать неоднозначности. В обоих случаях переопределение не включает в себя ограничения, но наследует их от базового класса. Если базовый класс не применяет ограничение class или struct , производные классы должны каким-либо образом указывать переопределение, применяемое к базовому методу без ограничения. Производный default метод применяет ограничение. Ограничение default не уточняет ни ограничение class , ни struct .

Неуправляемое ограничение

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

unsafe public static byte[] ToByteArray(this T argument) where T : unmanaged

В примере выше метод необходимо компилировать в контексте unsafe , так как он использует оператор sizeof для типа, не известного как встроенный тип. Без ограничения unmanaged оператор sizeof недоступен.

Ограничение unmanaged подразумевает ограничение struct и не может использоваться совместно с ним. Поскольку ограничение struct подразумевает ограничение new() , ограничение unmanaged также не может использоваться с ограничением new() .

Ограничения делегата

Можно использовать System.Delegate или System.MulticastDelegate в качестве ограничения базового класса. В среде CLR это ограничение всегда было разрешено, но в языке C# оно было запрещено. Ограничение System.Delegate позволяет написать код, который работает с делегатами типобезопасным образом. Следующий код определяет метод расширения, который объединяет два делегата при условии, что они одного типа:

public static TDelegate? TypeSafeCombine(this TDelegate source, TDelegate target) where TDelegate : System.Delegate => Delegate.Combine(source, target) as TDelegate; 

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

Action first = () => Console.WriteLine("this"); Action second = () => Console.WriteLine("that"); var combined = first.TypeSafeCombine(second); combined!(); Func test = () => true; // Combine signature ensures combined delegates must // have the same type. //var badCombined = first.TypeSafeCombine(test); 

Если раскомментировать последнюю строку, она не будет компилироваться. first и test являются типами делегатов, но это разные типы делегатов.

Ограничения перечисления

Можно также указать System.Enum тип в качестве ограничения базового класса. В среде CLR это ограничение всегда было разрешено, но в языке C# оно было запрещено. Универсальные шаблоны с System.Enum предоставляют типобезопасное программирование для кэширования результатов использования статических методов в System.Enum . В следующем примере выполняется поиск всех допустимых значений для типа перечисления и создается словарь, который сопоставляет эти значения с их строковым представлением.

public static Dictionary EnumNamedValues() where T : System.Enum < var result = new Dictionary(); var values = Enum.GetValues(typeof(T)); foreach (int item in values) result.Add(item, Enum.GetName(typeof(T), item)!); return result; > 

Enum.GetValues и Enum.GetName используют отражение, которое влияет на производительность. Вы можете не повторять вызовы, требующие отражения, а вызвать EnumNamedValues для создания коллекции, которая кэшируется и используется повторно.

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

enum Rainbow
var map = EnumNamedValues(); foreach (var pair in map) Console.WriteLine($":\t"); 

Аргументы типа реализуют объявленный интерфейс

В некоторых сценариях требуется, чтобы аргумент, предоставленный для параметра типа, реализул этот интерфейс. Например:

public interface IAdditionSubtraction where T : IAdditionSubtraction

Этот шаблон позволяет компилятору C# определить содержащий тип для перегруженных операторов или любого static virtual или static abstract метода. Он предоставляет синтаксис, чтобы операторы добавления и вычитания могли быть определены для содержащего типа. Без этого ограничения параметры и аргументы должны быть объявлены в качестве интерфейса, а не параметр типа:

public interface IAdditionSubtraction where T : IAdditionSubtraction  < public abstract static IAdditionSubtractionoperator +( IAdditionSubtraction left, IAdditionSubtraction right); public abstract static IAdditionSubtraction operator -( IAdditionSubtraction left, IAdditionSubtraction right); > 

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

См. также

  • System.Collections.Generic
  • Введение в универсальные шаблоны
  • Универсальные классы
  • Ограничение new

Совместная работа с нами на GitHub

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

C #: ограничить длину строки? [Дубликат]

Строки в С# неизменяемы, и в некотором смысле это означает, что они фиксированного размера.
Однако вы не можете ограничить строковую переменную, чтобы принимать только n-символьные строки. Если вы определяете строковую переменную, ей может быть назначена любая строка. Если усечение строк (или метаданных ошибок) является неотъемлемой частью вашей бизнес-логики, подумайте о том, чтобы сделать это в настройках свойств вашего конкретного класса (это то, что предложил Джон, и это самый естественный способ создания ограничений на значения в .NET).

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

const int MaxLength = 5; var name = "Christopher"; if (name.Length > MaxLength) name = name.Substring(0, MaxLength); // name = "Chris" 

Dan Abramov 29 сен. 2010, в 22:37
Поделиться

Я бы сказал, что все строки имеют фиксированную длину в .NET. Но вы не можете объявить, что переменная может принимать только строки определенной длины.

Как ограничить значение переменной?

Хочу реализовать в своей игре уровни предметов, но как сделать максимальный уровень? Например, что бы он был 30. Есть идея, при прокачке уровня если он будет равнятся 30, то просто пропадет кнопка, но как сделать это грамотно? Помню, как-то ограничивал значение поворота камеры, что бы нельзя было вертеть головой на 360 градусов вверх. Возможно, с помощью функции Math.Lerp, но я не помню) Подскажите.

Отслеживать
задан 12 июн 2019 в 8:46
JediMan4ik JediMan4ik
235 2 2 серебряных знака 10 10 бронзовых знаков
Как ограничить значение переменной? — myVariable = Math.Min(30, myVariable);
12 июн 2019 в 8:52

Но ведь это нужно будет вызывать постоянно при прокачке уровня. Можно вместо этого написать просто if (myVariable > 30) myVariable = 30;

12 июн 2019 в 9:05
Можно и так. Оформите ответом? 🙂
12 июн 2019 в 9:57
Мне нужно что бы переменная была «ограничена» постоянно, а не каждый вызов.
12 июн 2019 в 11:04
А если использовать не переменную, а своиство. А ограницение установоте в операторе set
12 июн 2019 в 11:09

1 ответ 1

Сортировка: Сброс на вариант по умолчанию

Использовать не переменную, а свойство. А ограничение установить в операторе set

 private int _myVariable; public int myVariable < get < return _myVariable; >set < _myVariable = Math.Min(30,value); >> 

Отслеживать
ответ дан 12 июн 2019 в 12:00
Leonid Malyshev Leonid Malyshev
945 5 5 серебряных знаков 15 15 бронзовых знаков

  • c#
  • unity3d
    Важное на Мете
Похожие

Подписаться на ленту

Лента вопроса

Для подписки на ленту скопируйте и вставьте эту ссылку в вашу программу для чтения RSS.

Дизайн сайта / логотип © 2024 Stack Exchange Inc; пользовательские материалы лицензированы в соответствии с CC BY-SA . rev 2024.4.30.8466

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *