面向对象的Casting问题

时间:2017-10-11 19:10:38

标签: c# oop casting

我有一个投射问题,我想知道是否有人能够帮我看看如何解决这个问题?

基本上我正在尝试创建一个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程序......

我正在考虑使用泛型,我已经和他们玩了一些但是我也遇到了一些麻烦。

2 个答案:

答案 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();
    }
}