Вот решение, что я думаю, лучше, чем кто-либо отправленный до сих пор:
public static byte[] hexStringToByteArray(String s) {
int len = s.length();
byte[] data = new byte[len / 2];
for (int i = 0; i < len; i += 2) {
data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
+ Character.digit(s.charAt(i+1), 16));
}
return data;
}
Причины, почему это - улучшение:
Безопасный с начальными нулями (в отличие от BigInteger) и с отрицательными значениями байта (в отличие от Byte.parseByte)
не преобразовывает Строку в char[]
или создает объекты StringBuilder и Строки для каждого байта.
зависимости библиотеки No, которые не могут быть доступны
, Не стесняются добавлять проверку аргументов через assert
или исключения, если аргумент, как известно, не безопасен.
Чтобы выполнить эту работу, нужно перебирать список и приводить элементы. Это можно сделать с помощью ConvertAll:
List<A> listOfA = new List<C>().ConvertAll(x => (A)x);
Вы также можете использовать Linq:
List<A> listOfA = new List<C>().Cast<A>().ToList();
Прежде всего, прекратите использовать непонятные имена классов, такие как A, B, C. Используйте Animal, Mammal, Giraffe или Food, Fruit, Orange или что-то еще, где взаимосвязь ясна .
Тогда ваш вопрос: «Почему я не могу назначить список жирафов переменной типа list of animal, если я могу назначить жирафа переменной типа animal?»
Ответ: предположим, вы мог. Что же тогда может пойти не так?
Что ж, вы можете добавить Тигра в список животных. Предположим, мы позволяем вам поместить список жирафов в переменную, которая содержит список животных. Затем вы пытаетесь добавить в этот список тигра. Что происходит? Хотите, чтобы в списке жирафов был тигр? Вы хотите крушение? или вы хотите, чтобы компилятор защитил вас от сбоя, в первую очередь сделав присвоение незаконным?
Мы выбираем последнее.
Этот вид преобразования называется «ковариантным» преобразованием. В C # 4 мы позволим вам выполнять ковариантные преобразования для интерфейсов и делегатов , когда известно, что преобразование всегда безопасно . См. Подробности в статьях моего блога о ковариации и контравариантности. (На этой неделе в понедельник и четверг будет новый доклад по этой теме.)
Что касается того, почему это не работает, может быть полезно понять ковариацию и контравариантность .
Просто чтобы показать, почему это не должно работают, вот изменение предоставленного вами кода:
void DoesThisWork()
{
List<C> DerivedList = new List<C>();
List<A> BaseList = DerivedList;
BaseList.Add(new B());
C FirstItem = DerivedList.First();
}
Должно ли это работать? Первый элемент в списке имеет тип «B», но тип элемента DerivedList - C.
Теперь предположим, что мы действительно просто хотим создать общую функцию, которая работает со списком некоторого типа, который реализует A , но нас не волнует, какой это тип:
void ThisWorks<T>(List<T> GenericList) where T:A
{
}
void Test()
{
ThisWorks(new List<B>());
ThisWorks(new List<C>());
}
Потому что C # не поддерживает этот тип наследования преобразования в настоящий момент .