简体   繁体   English

将通用基础对象转换为派生类型

[英]Casting Generic base object to derived type

What is the correct way to cast a base class that is using generics back to its derived type? 将使用泛型的基类转换回其派生类型的正确方法是什么?

I have the following object implemented. 我实现了以下对象。

Note that the "Save" method is calling the "WriteSettings" method here (takes in a BaseSettings object) 请注意,“保存”方法在此处调用“ WriteSettings”方法(采用BaseSettings对象)

public class Settings1
{
    public string strData;
}

public class BaseSettings<T>
{
    T settings;
    public iSettingsDestination Destination;

    public bool Save()
    {
        return Destination.WriteSettings(this);
    }
}

public class Settings1Manager : BaseSettings<Settings1>
{
    public bool DoSomething()
    {
        return true;
    }
}

I have created an interface iSettingsDestination that will always use the base class (BaseSettings) to pass the object. 我创建了一个接口iSettingsDestination,它将始终使用基类(BaseSettings)来传递对象。 Classes derived from iSettingsDestination can choose which object types to handle. 从iSettingsDestination派生的类可以选择要处理的对象类型。 I want to be able to pass this object as it's base type into a method, determine the derived type, and reverse the cast. 我希望能够将此对象作为基本类型传递给方法,确定派生类型,并反向转换。 (see below) I receive a compile error when trying to cast back to the derived type. (请参阅下文)在尝试强制转换回派生类型时收到编译错误。

public interface iSettingsDestination
{
    bool WriteSettings<T>(BaseSettings<T> settings);
}

public class FileDestination : iSettingsDestination
{
    bool WriteSettings1ManagerToFile(Settings1Manager settings)
    {
        // write to file
        return true;
    }

    bool WriteSettings<T>(BaseSettings<T> settings)
    {
        if (typeof(Settings1Manager).IsAssignableFrom(settings.GetType()))
        {
            // generates error
            // Cannot convert type 'BaseSettings<T>' to 'Settings1Manager'
            return WriteSettings1ManagerToNetwork((Settings1Manager)settings);
        }

        // unhandled object type
        return false;
    }

}

I want to be able to call the code like below. 我希望能够像下面这样调用代码。 For the example here, I only show 1 type of "Destination" and "Settings" but you can imagine that there are many different types that can be used here. 对于此处的示例,我仅显示“目的地”和“设置”的一种类型,但是您可以想象这里可以使用许多不同的类型。

    void main()
    {
        Settings1Manager settings1 = new Settings1Manager();
        settings1.Destination = new FileDestination();
        settings1.Save(); // saves to a file
    }

I am able to do this with other base classes but it seems that using generics here causes issues. 我可以对其他基类执行此操作,但似乎在此处使用泛型会导致问题。

1) How can I correctly make the cast back to the derived type in the call WriteSettings1ManagerToNetwork((Settings1Manager)settings); 1)如何在调用WriteSettings1ManagerToNetwork((Settings1Manager)settings);中正确地将类型转换回派生类型;

2) Does anyone see any issues blatant misuse of the Generics/interface/etc logic here? 2)有人在这里看到任何明显滥用​​泛型/接口/等逻辑的问题吗?

Thanks in advance for any help. 在此先感谢您的帮助。

A reference declared as BaseSettings<T> may or may not refer to an actual instance of Settings1Manager . 声明为BaseSettings<T>引用BaseSettings<T> 或可以不引用Settings1Manager的实际实例。 That's how inheritance works. 这就是继承的方式。 In fact though, what you're doing is casting a base type reference that's actually referring to an object that you've just confirmed actually is of the derived type. 但是实际上,您正在执行的是强制转换基本类型引用,该引用实际上是指您刚刚确认实际上派生类型的对象。

settings as Settings1Manager will compile, because as will just return null if the cast fails. settings as Settings1Managersettings as Settings1Manager进行编译,因为如果强制转换失败, as只会返回null You and I know that particular cast won't fail, but the compiler just follows its rules. 您和我知道特定的转换不会失败,但是编译器仅遵循其规则。

if (typeof(Settings1Manager).IsAssignableFrom(settings.GetType()))
{
    return WriteSettings1ManagerToNetwork(settings as Settings1Manager);
}

This works too, because you can cast anything to object and you can cast object to anything. 这也可行,因为您可以将任何object投射到object ,也可以将object投射到object But you don't want people seeing your name on code that looks like this. 但是,您不希望人们在看起来像这样的代码上看到您的名字。

return WriteSettings1ManagerToFile((Settings1Manager)(object)settings);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM