【发布时间】:2020-02-28 04:01:56
【问题描述】:
在 C# 中使用泛型类和方法时,我需要您的帮助。当我在ProduceData中调用EnqueObject方法时,在EnqueueObject(block)那一行,出现错误:cannot convert 'byte[ ]' 到 'T'。如有任何建议,我将不胜感激。
(我已经简化了我的代码,因为我相信我的问题是非常基本的)。
class CompressingProducer<T>
{
Queue<T> _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);
block = new byte[Settings.blockSize];
}
}
private void EnqueueObject(T data)
{
_queue.Enqueue(data);
}
}
更新
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
using System.IO;
namespace GZipTestProject
{
class CompressingProducer<T>
{
Thread _producerThread;
readonly object _lock;
Queue<T> _queue;
/// <summary>
/// Reads data in chunks (as byte[]) or as CompressedData objects from the file stream and inserts them into a queue
/// </summary>
/// <param name="fileInputStream">Connected to the file from which data will be read</param>
public CompressingProducer(Stream fileInputStream) {
_lock = ProducerConsumer<T>.getLock();
_queue = ProducerConsumer<T>.getQueue();
_producerThread = new Thread(ProduceData);
_producerThread.Start(fileInputStream);
}
/// Takes a file input stream parameter from which data will be read and put into a queue for a consumer.
/// The parameter of this method must be object because it will be passed as a delegate to a new thread.
public void ProduceData(object fileInputStream)
{
if (GZipTest.GetActionType() == ActionType.Compress) {
byte[] block = new byte[Settings.blockSize];
int bytesRead;
while ((bytesRead = ((Stream)fileInputStream).Read(block, 0, Settings.blockSize)) > 0)
{
if (bytesRead < block.Length)
{
byte[] block2 = new byte[bytesRead];
Array.Copy(block, block2, bytesRead);
block = block2;
}
EnqueueObject(block); // put the data block into the queue
block = new byte[Settings.blockSize];
}
}
private void EnqueueObject(T data) //byte[] block or CompressedData
{
lock (_lock)
{
while (_queue.Count >= Settings.maxQueueSize)
{
Monitor.Wait(_lock); // suspends the whole main thread of the application
}
_queue.Enqueue(data);
if (_queue.Count == 1)
{
// wake up any blocked dequeue, i.e. the consumer thread
Monitor.PulseAll(_lock);
}
}
}
}
}
我了解到您需要进一步说明该程序的工作原理。它应该用于压缩和解压缩。首先,它按块(字节数组)读取文件,然后压缩块,将它们放入我自己的类 CompressedData 的对象中,并将它们序列化为一个文件。在解压过程中,对象被反序列化,压缩后的字节数组被解压到一个新文件中。它使用生产者-消费者模式,因此有一个“生产者”将元素放入队列中,队列本身和一个“消费者”获取元素并处理所需的操作(压缩/解压缩)。我想使用我的类 CompressingProducer 作为操作、压缩和解压缩的“生产者”,这意味着它在压缩过程中将字节数组排入队列,在解压缩过程中将我的类 CompressedData 的对象排入队列。这就是我尝试使用泛型的原因。
【问题讨论】:
-
block是byte[]。EnqueueObject只需要T。您必须以某种方式将byte[]转换为T,然后才能通过它。告诉我们更多相关信息? -
一般问题是您传递的值是特定类型的
byte[],而对此没有任何保证,甚至没有任何理由相信泛型类型参数T将是byte[]。您的队列必须有T类型的元素,但编译器无法证明T是byte[]。事实上,如果它可以,那么通用方面将毫无意义,因为T永远不可能是byte[]以外的任何东西。如果 you 是肯定的T始终是byte[],那么您可以按照标记的重复项进行投射。但它仍然留下为什么?的问题 -
@PeterDuniho - 我重新提出了这个问题,因为我认为很明显这不是关于铸造,而是关于转换。重复的内容纯粹是关于铸造。
-
@PeterDuniho 谢谢你的回答。 T 不会总是 byte[],这就是为什么我决定使用带有泛型参数的方法。我相信 T 可以代表任何类型的对象 - ?
-
@AliceHekrdlová - 与初学者交流并不累人 - 如果初学者有礼貌并且愿意改进他们的问题(就像你一样),那将是一种乐趣。到目前为止,我唯一的评论是您不应该编辑问题以使现有的 cmets 和答案无效。所以我重新编辑了你的问题。我希望它仍然清楚。
标签: c# generics generic-programming generic-collections