我有一个投射问题,我想知道是否有人能够帮我看看如何解决这个问题?
基本上我正在尝试创建一个CSV生成器控制台程序,该程序将从数据库中获取机器记录列表并将它们放入CSV中。
以下代码已简化,但与我目前的实施方式大致相似:
public interface IRecord
{
}
public class MachineRecord : IRecord
{
string Name {get;set;}
string ErrorCount {get;set;}
}
public interface IRecordStore
{
string GenerateRecord(IRecord record);
}
public class CSVMachineRecordStore : IRecordStore
{
public string GenerateRecord(IRecord record)
{
var machineRecord = (MachineRecord)record;
var strBuilder = new StringBuilder();
strBuilder.Append(machineRecord.Name);
strBuilder.Append(machineRecord.ErrorCount);
return strBuilder.ToString();
}
}
所以基本上我在这里创建了一个继承自IRecordStore的类,在我们的例子中,我们必须创建一个GenerateRecord的实现。这里的问题是我必须转换类型为MachineRecord的记录,否则编译器会抛出一个转换错误,这是由于Record没有设置任何属性。
是否可以在此实现中没有直接强制转换,因此这行代码将如下:
public class CSVMachineRecordStore : IRecordStore
{
public string GenerateRecord(IRecord record)
{
var machineRecord = record; //we want to remove the explicit cast
var strBuilder = new StringBuilder();
strBuilder.Append(machineRecord.Name);
strBuilder.Append(machineRecord.ErrorCount);
return strBuilder.ToString();
}
}
我知道我可以通过向IRecord添加Name和ErrorCount属性来解决这个问题,但是IRecord是一个非常通用的接口,可以有任何东西。
我们希望能够创建一个可以处理机器记录,客户记录,员工记录,供应商记录等的CSV程序......
我正在考虑使用泛型,我已经和他们玩了一些但是我也遇到了一些麻烦。
答案 0 :(得分:3)
使用泛型:
public interface IRecordStore<T> where T:IRecord
{
string GenerateRecord(T record);
}
然后执行:
public class CSVMachineRecordStore : IRecordStore<MachineRecord>
{
public string GenerateRecord(MachineRecord record)
{
var machineRecord = record; //we want to remove the explicit cast
var strBuilder = new StringBuilder();
strBuilder.Append(machineRecord.Name);
strBuilder.Append(machineRecord.ErrorCount);
return strBuilder.ToString();
}
}
我匆忙写了这个,一定要查看愚蠢的错误。
答案 1 :(得分:0)
当IRecord
实例不是MachineRecord
的实例时,会发生类型转换异常。
要回答您的问题如何解决投射问题,您应该查看as operator。
但是,对我来说,这似乎使IRecordStore
界面通用可以帮助您防止您遇到的类型问题:
[编辑]我注意到,因为IRecordStore是一个接口,你甚至可以制作通用类型contravariant。这允许您分配变量
类型IRecordStore<IRecord>
,其实例为IRecordStore<MachineRecord>
或更明确CSVMachineRecordStore
。
public interface IRecordStore<in T> where T : IRecord
{
string GenerateRecord(T record);
}
public class CSVMachineRecordStore : IRecordStore<MachineRecord>
{
public string GenerateRecord(MachineRecord record)
{
var machineRecord = record;
var strBuilder = new StringBuilder();
strBuilder.Append(machineRecord.Name);
strBuilder.Append(machineRecord.ErrorCount);
return strBuilder.ToString();
}
}