Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / WinForms, .Net Framework [игнор отключен] [закрыт для гостей] / Ограничить присваимые значения типу int на этапе компиляции. / 12 сообщений из 12, страница 1 из 1
19.05.2015, 21:49
    #38963339
ProBiotek
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Ограничить присваимые значения типу int на этапе компиляции.
Привет.
Туплю что-то. Мне нужно позволить чтобы в свойство можно было ввести только число от 1 до 5. Хочется чтобы это проверялось не в рантайме а прямо при разработке.

На ум приходит только такая тупая конструкция.

Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
    public enum MyRange
    {
     One=1, Two, Three
    }

....

var myfield = (int)MyRange.Two;


Числа имен не имеют. Т.е. я не могу их обозвать как то по умному. Просто от 1 до 5.

PS. В Дельфи есть возможность создать свой тип на основе int, ограничив допустимые значения.
...
Рейтинг: 0 / 0
19.05.2015, 21:56
    #38963341
Shocker.Pro
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Ограничить присваимые значения типу int на этапе компиляции.
а чем не нравится этот вариант?
...
Рейтинг: 0 / 0
19.05.2015, 23:22
    #38963383
Roman Mejtes
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Ограничить присваимые значения типу int на этапе компиляции.
ProBiotek,

Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
149.
150.
151.
152.
153.
154.
155.
156.
157.
158.
159.
160.
161.
162.
163.
164.
165.
166.
167.
168.
169.
170.
171.
172.
173.
174.
175.
176.
177.
178.
179.
180.
181.
182.
183.
184.
185.
186.
187.
188.
189.
190.
191.
using System;
using System.Globalization;

namespace ConsoleApplication4
{

    public struct Int5 : IComparable, IFormattable, IConvertible, IComparable<Int5>, IEquatable<Int5>
    {
        public override int GetHashCode()
        {
            return _value;
        }

        private readonly int _value;

        private Int5(int value)
        {
            _value = value;
        }

        public const int MinValue = 0;
        public const int MaxValue = 5;

        public int CompareTo(object value)
        {
            if (value == null) { return 1; }
            if (value is Int5)
            {
                var i = (int)value;
                if (_value < i) return -1;
                if (_value > i) return 1;
                return 0;
            }
            throw new ArgumentException();
        }

        public TypeCode GetTypeCode()
        {
            return TypeCode.Int32;
        }

        public string ToString(string format, IFormatProvider formatProvider)
        {
            return _value.ToString(format, formatProvider);
        }
        #region IConvertible
        public bool ToBoolean(IFormatProvider provider)
        {
            return _value != 0;
        }
        public char ToChar(IFormatProvider provider)
        {
            return Convert.ToChar(_value, provider);
        }
        public sbyte ToSByte(IFormatProvider provider)
        {
            return Convert.ToSByte(_value, provider);
        }
        public byte ToByte(IFormatProvider provider)
        {
            return Convert.ToByte(_value, provider);
        }
        public short ToInt16(IFormatProvider provider)
        {
            return Convert.ToInt16(_value, provider);
        }
        public ushort ToUInt16(IFormatProvider provider)
        {
            return Convert.ToUInt16(_value, provider);
        }
        public int ToInt32(IFormatProvider provider)
        {
            return Convert.ToInt32(_value, provider);
        }
        public uint ToUInt32(IFormatProvider provider)
        {
            return Convert.ToUInt32(_value, provider);
        }
        public long ToInt64(IFormatProvider provider)
        {
            return Convert.ToInt64(_value, provider);
        }
        public ulong ToUInt64(IFormatProvider provider)
        {
            return Convert.ToUInt64(_value, provider);
        }
        public float ToSingle(IFormatProvider provider)
        {
            return Convert.ToSingle(_value, provider);
        }
        public double ToDouble(IFormatProvider provider)
        {
            return Convert.ToDouble(_value, provider);
        }
        public decimal ToDecimal(IFormatProvider provider)
        {
            return Convert.ToDecimal(_value, provider);
        }
        public DateTime ToDateTime(IFormatProvider provider)
        {
            return Convert.ToDateTime(_value, provider);
        }
        public string ToString(IFormatProvider provider)
        {
            return Convert.ToString(_value, provider);
        }
        public object ToType(Type conversionType, IFormatProvider provider)
        {
            throw new Exception("can't converto to any type");
        }
        #endregion
        public int CompareTo(Int5 value)
        {
            if (value is Int5)
            {
                var i = value._value;
                if (_value < i) return -1;
                if (_value > i) return 1;
                return 0;
            }
            throw new ArgumentException();
        }
        public bool Equals(Int5 other)
        {
            return _value == other._value;
        }
        public override bool Equals(Object obj)
        {
            if (!(obj is Int5))  { return false; }
            return _value == ((Int5)obj)._value;
        }
        public static int Parse(String s, NumberStyles style, IFormatProvider provider)
        {
            return int.Parse(s, style, NumberFormatInfo.GetInstance(provider));
        }
        public static bool TryParse(String s, out Int32 result)
        {
            return int.TryParse(s, NumberStyles.Integer, NumberFormatInfo.CurrentInfo, out result);
        }

        public static Int5 operator +(Int5 a, Int5 b)
        {
            var result = a._value + b._value;
            Validation(result);
            return new Int5(result);
        }

        public static Int5 operator -(Int5 a, Int5 b)
        {
            var result = a._value - b._value;
            Validation(result);
            return new Int5(result);
        }

        public static Int5 operator *(Int5 a, Int5 b)
        {
            var result = a._value * b._value;
            Validation(result);
            return new Int5(result);
        }

        public static Int5 operator /(Int5 a, Int5 b)
        {
            var result = a._value / b._value;
            Validation(result);
            return new Int5(result);
        }
        public static implicit operator Int5(int a)
        {
            Validation(a);
            return new Int5(a);
        }
        private static void Validation(int value)
        {
            if (value > MaxValue || value < MinValue) throw new ArgumentOutOfRangeException();
        }

    }
    public class TestProgram
    {
        static void Main()
        {
            Int5 a, b;
            a = 2;
            b = 6;
            Int5 test = a + b;
            Console.Write(test);
            Console.ReadKey();
        }
    }
}


думаю автору нужно, что то вроде этого.
...
Рейтинг: 0 / 0
19.05.2015, 23:29
    #38963388
petalvik
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Ограничить присваимые значения типу int на этапе компиляции.
ProBiotek,

можно использовать Code Contracts. Во всяком случае, можно задать требуемое поведение для свойств, а вот для полей - не уверен.
...
Рейтинг: 0 / 0
19.05.2015, 23:34
    #38963391
Roman Mejtes
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Ограничить присваимые значения типу int на этапе компиляции.
petalvik,

для полей можно создать структуру где задать нужное поведение.
вот только не пойму одного.
для структуры int16 IDE проверяет значение.
то есть Int16 a = 10000; сообщает об ошибке, хоть оператор присвоения перегружен для типа int.
не очень понятно, как заставить его проверять свою структуру
...
Рейтинг: 0 / 0
20.05.2015, 00:00
    #38963402
petalvik
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Ограничить присваимые значения типу int на этапе компиляции.
Всё-таки можно и для поля задать инвариант с помощью метода, помеченного атрибутом ContractInvariantMethod.

Всё никак не проштудирую эти контракты как следует.
Удручает скорость проверки. Скорость компиляции намного дольше с включенными контрактами.
...
Рейтинг: 0 / 0
20.05.2015, 11:35
    #38963816
ProBiotek
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Ограничить присваимые значения типу int на этапе компиляции.
Roman Mejtes,

Ох жеж. Сколько кода то )))

Но оно же не будет работать в дезайн-тайме ! В рантайме я и так могу сам все проверить. Ибо это свойство (в которое я хочу сохранять числа) принадлежит классу. А класс я буду валидировать.

Просто захотелось чего-то странного, под вечер не_пятницы.
Я подумал. И решил, что пожалуй оставлю свой вариант с enum. Буду просто и использовать прямо его (а не int вообще), а уже при сохранении в БД и буду преобразовывать.

Для чего мне вообще это нужно.
У меня есть показатели характеристики товара. Их 10 штук. Каждое из них - это оценка типа "удобство носки", "прочность". Все они могут принимать оценку от 1 до 5.
...
Рейтинг: 0 / 0
20.05.2015, 18:36
    #38964537
petalvik
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Ограничить присваимые значения типу int на этапе компиляции.
ProBiotek,

нет желания попробовать Code Contracts? Новомодная фича от MS. Можно сразу прослыть крутым прогером :).

Так ограничиваем диапазон значений свойству:
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
int x;

int X
{
    get { return x; }
    set
    {
        Contract.Requires(value >= 1 && value <= 5);
        x = value;
    }
}



Так задаём инвариант значений полю класса:
Код: c#
1.
2.
3.
4.
5.
6.
7.
int n;

[ContractInvariantMethod]
void nInvariant()
{
    Contract.Invariant(this.n >= 1 && this.n <= 5);
}



Если теперь в свойствах проекта на вкладке Code Contracts поставить галочку Perform Static Contract Checking, снять галочку Check in background и поставить галочку Fail build on warnings - проект не скомпилируется, если будут заданы не подходящие значения. Ошибки будут указаны привычным способом.
...
Рейтинг: 0 / 0
20.05.2015, 18:41
    #38964541
Roman Mejtes
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Ограничить присваимые значения типу int на этапе компиляции.
petalvikЕсли теперь в свойствах проекта на вкладке Code Contracts поставить галочку Perform Static Contract Checking, снять галочку Check in background и поставить галочку Fail build on warnings - проект не скомпилируется, если будут заданы не подходящие значения. Ошибки будут указаны привычным способом.
что то у меня нет в 2012 такой вкладки, только в 2013 есть или включить где то надо?
...
Рейтинг: 0 / 0
20.05.2015, 19:10
    #38964558
petalvik
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Ограничить присваимые значения типу int на этапе компиляции.
Roman Mejtes,

нужно скачать CodeContracts . И после установки перезапустить Студию (если она запущена была), чтобы она подхватила изменения.
...
Рейтинг: 0 / 0
20.05.2015, 19:21
    #38964565
Roman Mejtes
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Ограничить присваимые значения типу int на этапе компиляции.
petalvik,

ну всё еще пару мегабайт и я стану крутым прогером =)
...
Рейтинг: 0 / 0
21.05.2015, 12:31
    #38965126
ProBiotek
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Ограничить присваимые значения типу int на этапе компиляции.
petalvik,

Читал я давно. Дино Эспозито еще года 3-4 назад писал статьи в МСДН магазине.

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

В общем это наверное круто, когда нет командной разработке, и пишешь свой проект.
Но когда проект пишет несколько человек, придется им всем устанавливать и настраивать этот компонент. Плюс как-то обеспечивать чтобы новый участник, временно подключившийся к проекту, тоже быстро поставил эту штуку - а это не так просто, нужно сколько то телодвижений.
Еще, наверное, нужно будет всем вместе синхронно переходить на новые версии. У нас есть проект, в котором используется EF4 (где модели edmx) и всем страшно переводить его на EF6 Code First. Там проще переписать, выпустив новую версию программы.

Как только MS сами решат что технология созрела и официально включат ее в VS. Тогда можно будет использовать. Но до тех пор, пока продукт еще в развитии, его удел это мелкие проекты, которые легко поддерживать и быстро переписать при изменении инструмента.

PS. Это как с TPL. Году в 2008 был Parallel Extensions for .Net Framewok (PFX). Кто хотел, использовал на свой страх и риск (за что им спасибо, т.к. благодаря таким исследователям и развивалась технология). Потом появился TPL. Потом Async.
Вот я бы подождал с контрактами в крупных проектах, пока они хотя бы не выйдут на стадию "TPL" с полноценной поддержкой в VS без бубна :)
...
Рейтинг: 0 / 0
Форумы / WinForms, .Net Framework [игнор отключен] [закрыт для гостей] / Ограничить присваимые значения типу int на этапе компиляции. / 12 сообщений из 12, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]