Внутри класса T является обобщенным типом c, он не представляет какой-либо тип или тип, который может принимать значения любого типа, он представляет особый тип c, определенный параметром.
Когда вы объявляете переменную CompressingProducer, вам нужно передать параметр типа
CompressingProducer<byte[]> producer = new CompressingProducer<byte[]>();
T = byte [] . В этом случае T совпадает с типом byte [], но мы говорим о обобщенных c типах, которые могут быть любыми типами, а не только byte [].
Рассмотрим объявление следующего за T сейчас: string
CompressingProducer<string> producer = new CompressingProducer<string>();
T = строка , но внутри метода CompressingProducer.EnqueueObject требуется параметр T, параметр не равен байту [], равен строке.
Обобщения помогают обрабатывать любой тип , но тип зависит от типа, переданного в качестве параметра при объявлении переменной. Проблема состоит в том, чтобы относиться к типу T как к любому типу внутри класса CompressingProducer. T - это тип, определяемый параметром при объявлении любой переменной CompressingProducer. По этой причине вы не можете передавать никакое значение методу EnqueueObject, только значения типа T.
Всегда рассматривайте T как виртуальный / вымышленный / воображаемый тип, который является реальным типом, когда передаете тип как параметр при создании переменная.
Если вам нужно обработать любой тип в очереди, используйте класс объекта в параметре типа, в C# любой класс исключает объект, наследуемый от объекта.
class CompressingProducer
{
Queue<Object> _queue;
public void ProduceData(object fileInputStream)
{
byte[] block = new byte[Settings.blockSize];
int bytesRead;
while ((bytesRead = ((Stream)fileInputStream).Read(block, 0, Settings.blockSize)) > 0)
{
EnqueueObject(block);//Needs object of T type.
block = new byte[Settings.blockSize];
}
}
private void EnqueueObject(Object data)
{
_queue.Enqueue(data);
}
}
Мое окончательное решение - изменить метод ProduceData , добавить еще один параметр типа Fun c, этот параметр является делегатом для преобразования из байта [] в тип, переданный в качестве параметра.
Два примера использования:
T = строка
T = Персона (Тип примера)
class CompressingProducer<T>
{
Queue<T> _queue;
public void ProduceData(Stream fileInputStream, Func<byte[], T> convert)
{
byte[] block = new byte[Settings.blockSize];
int bytesRead;
while ((bytesRead = ((Stream)fileInputStream).Read(block, 0, Settings.blockSize)) > 0)
{
EnqueueObject(convert(block));//Using convert function, from byte[] ==> to T
block = new byte[Settings.blockSize];
}
}
private void EnqueueObject(T data)
{
_queue.Enqueue(data);
}
}
class Program
{
public static string ConvertData(byte[] data)
{
return Encoding.UTF8.GetString(data);
}
class Person
{
public long Id { get; set; }
public String Name { get; set; }
public byte[] ToBytes()
{
//this is aproach example, Needs more improvements
return BitConverter.GetBytes(Id).Concat(Encoding.UTF8.GetBytes(Name).Take(Settings.blockSize - 8/* long type size of Id */)).ToArray(); //byte[] of blockSize size
}
public static Person ToPerson(byte[] bytes)
{
return new Person
{
Id = BitConverter.ToInt64(bytes.Take(8).ToArray()),
Name = Encoding.UTF8.GetString(bytes.Skip(8).ToArray())
};
}
}
static void Main(string[] args)
{
//EXAMPLE 1
CompressingProducer<string> producer = new CompressingProducer<string>();
using (Stream filestream = File.OpenRead("path to file"))
{
//ProduceData(Stream fileInputStream, Func<byte[], string> convert), T now is string type.
producer.ProduceData(filestream, data => Encoding.UTF8.GetString(data));//Using lambda expression.
producer.ProduceData(filestream, ConvertData);//Using delegate. //Same result as lambda.
}
//EXAMPLE 2
CompressingProducer<Person> personProducer = new CompressingProducer<Person>();
using (Stream filestream = File.OpenRead("path to file containing Person Blocks"))
{
//ProduceData(Stream fileInputStream, Func<byte[], Person> convert), T now is Person type.
personProducer.ProduceData(filestream, data => Person.ToPerson(data));//Using lambda expression.
}
Console.ReadLine();
}
}