Задача:
Написать коллекцию из которой можно извлекать значения по идентификатору без упаковки\распаковки в "System.Object".
Для решения этой задачи пробую использовать дженерик-метод:
class Program
{
static Dictionary<long, byte> _hashByte = new Dictionary<long, byte>();
static Dictionary<long, bool> _hashBoolean = new Dictionary<long, bool>();
static Dictionary<long, int> _hashInt32 = new Dictionary<long, int>();
static Dictionary<long, long> _hashInt64 = new Dictionary<long, long>();
// Возвращает значение по идентификаторуpublic static T GetValue<T>(long id) where T : struct
{
T value = default(T);
switch (typeof(T).Name)
{
case"Byte":
value = (T)_hashByte[id];
break;
case"Boolean":
value = (T)_hashBoolean[id];
break;
case"Int32":
value = (T)_hashInt32[id];
break;
case"Int64":
value = (T) _hashInt64[id];
break;
}
return value;
}
static void Main(string[] args)
{
long value = GetValue<long>(1);
}
}
Получаю сообщение компилятора:
" Cannot convert type 'byte' to 'T' "
" Cannot convert type 'bool' to 'T' "
...
Как правильно написать ограничение на значимый тип? В идеале нужен дженерик-метод, который может возвращать значения значимых типов C# и ссылочный тип string — такое возможно?
Здравствуйте, faa, Вы писали:
faa>Задача: faa>Написать коллекцию из которой можно извлекать значения по идентификатору без упаковки\распаковки в "System.Object". faa>Для решения этой задачи пробую использовать дженерик-метод: faa>... faa>Как правильно написать ограничение на значимый тип?
Дело не в ограничении на тип, с ним у вас все правильно.
Самое простое, что напрашивается:
1. В свитче делать не поиск значения, а поиск словаря, из которого делать лукап.
2. В case-ах делать сначала каст словаря к object-у, и только потом к целевому типу словаря.
Боксинга не будет, т.к. Dictionary — ссылочный тип.
А если по-чесноку, я бы написал по-другому:
private static class ValuesProvider<TKey, TValue>
{
public static readonly IDictionary<TKey, TValue> Values = new Dictionary<TKey, TValue>();
}
// Возвращает значение по идентификаторуpublic static T GetValue<T>(long id) where T : struct
{
return ValuesProvider<long, T>.Values[id];
}
Правда, х его з, будет ли это работать. Возможности проверить нет
L>Здравствуйте, faa, Вы писали: L>А если по-чесноку, я бы написал по-другому: L>
L>private static class ValuesProvider<TKey, TValue>
L>{
L> public static readonly IDictionary<TKey, TValue> Values = new Dictionary<TKey, TValue>();
L>}
L>// Возвращает значение по идентификатору
L>public static T GetValue<T>(long id) where T : struct
L>{
L> return ValuesProvider<long, T>.Values[id];
L>}
L>
L>Правда, х его з, будет ли это работать. Возможности проверить нет
не будет: string — это не struct
Здравствуйте, Аноним, Вы писали:
L>>// Возвращает значение по идентификатору L>>public static T GetValue<T>(long id) where T : struct L>>{ L>> return ValuesProvider<long, T>.Values[id]; L>>} L>>[/c#] L>>Правда, х его з, будет ли это работать. Возможности проверить нет А>не будет: string — это не struct
Были сомнения в работоспособности варианта с приватным generic-классом.
То, что класс не будет работать со строками — это и так понятно.
Здравствуйте, Lloyd, Вы писали:
L>Здравствуйте, faa, Вы писали:
faa>>Задача: faa>>Написать коллекцию из которой можно извлекать значения по идентификатору без упаковки\распаковки в "System.Object". faa>>Для решения этой задачи пробую использовать дженерик-метод: faa>>... faa>>Как правильно написать ограничение на значимый тип?
L>Дело не в ограничении на тип, с ним у вас все правильно. L>Самое простое, что напрашивается: L>1. В свитче делать не поиск значения, а поиск словаря, из которого делать лукап. L>2. В case-ах делать сначала каст словаря к object-у, и только потом к целевому типу словаря. L>
L>Боксинга не будет, т.к. Dictionary — ссылочный тип.
L>А если по-чесноку, я бы написал по-другому: L>
L>private static class ValuesProvider<TKey, TValue>
L>{
L> public static readonly IDictionary<TKey, TValue> Values = new Dictionary<TKey, TValue>();
L>}
L>// Возвращает значение по идентификатору
L>public static T GetValue<T>(long id) where T : struct
L>{
L> return ValuesProvider<long, T>.Values[id];
L>}
L>
L>Правда, х его з, будет ли это работать. Возможности проверить нет
<В свитче делать не поиск значения, а поиск словаря, из которого делать лукап.> Не понял идею.. Можно пример?
static class ValuesProvider<TKey, TValue>
{
private static IDictionary<TKey, TValue> _values = new Dictionary<TKey, TValue>();
// Возвращает значение по идентификаторуpublic static T GetValue<T>(long id) where T : struct
{
return ValuesProvider<long, T>._values[id];
}
public static void SetValue<T>(long id, T value) where T: struct
{
ValuesProvider<long, T>._values.Add(id, value);
}
}
class Program
{
static void Main(string[] args)
{
ValuesProvider<long, bool>.SetValue<bool>(0, true);
ValuesProvider<long, int>.SetValue<int>(0, 12345);
Console.WriteLine(ValuesProvider<long, bool>.GetValue<bool>(0));
Console.WriteLine(ValuesProvider<long, int>.GetValue<int>(0));
}
}
Это действительно работает, но я не пойму как? Я правильно понимаю, что вся "магия" заключается в использовании именно статического класса? Если не трудно поясните, как это работает?
abstract class Value
{
public abstract K GetValue<K>();
public static Value Create<T>(T value)
{
return new Value<T>(value);
}
}
sealed class Value<T> : Value
{
private T _value;
public Value(T value)
{
_value = value;
}
public override K GetValue<K>()
{
return __refvalue( __makeref(_value),K); ;
}
}
class Program
{
static void Main(string[] args)
{
Value value = Value.Create(42);
Console.WriteLine(value.GetValue<int>());
}
}
Здравствуйте, faa, Вы писали:
faa>Доброго времени суток! Прошу помощи.
faa>Задача: faa>Написать коллекцию из которой можно извлекать значения по идентификатору без упаковки\распаковки в "System.Object".
Задача — понятна. faa>Для решения этой задачи пробую использовать дженерик-метод:
Зачем? Вот правильное решение:
class Program
{
static Dictionary<long, byte> _hashByte = new Dictionary<long, byte>();
static Dictionary<long, bool> _hashBoolean = new Dictionary<long, bool>();
static Dictionary<long, int> _hashInt32 = new Dictionary<long, int>();
static Dictionary<long, long> _hashInt64 = new Dictionary<long, long>();
// Возвращает значение по идентификаторуpublic static byte GetValueByte(long id)
{
return _hashByte[id];
}
// Возвращает значение по идентификаторуpublic static bool GetValueBool(long id)
{
return _hashBoolean[id];
}
// Возвращает значение по идентификаторуpublic static int GetValueInt(long id)
{
return _hashInt32[id];
}
// Возвращает значение по идентификаторуpublic static long GetValueLong(long id)
{
return _hashInt64[id];
}
static void Main(string[] args)
{
long value = GetValueLong(1);
}
}
faa>Как правильно написать ограничение на значимый тип?
Никак. faa>В идеале нужен дженерик-метод, который может возвращать значения значимых типов C# и ссылочный тип string — такое возможно?
Без боксинга — нет. Непонятна цель ваших действий. Вызывающий код обязан указать нужный ему тип данных. При этом вы умеете возвращать вовсе не любой тип, а только один из известных вам заранее типов.
Фактически, дженерик-версия отличается от моей версии только наличием угловых скобочек в месте вызова метода. Ну и тем, что компилятор не проверяет, поддерживаемый ли тип передан в аргументе.
Вы нигде не используете тот факт, что ваш метод — generic. faa>Заранее благодарен!
Уйдемте отсюда, Румата! У вас слишком богатые погреба.