首页 > 解决方案 > 在 C# 泛型中传递“this”在没有强制转换的情况下不起作用

问题描述

我尝试了谷歌搜索和stackoverflow,但找不到我的具体问题的答案(甚至是有限的泛型知识)

所以我在这里发帖希望得到答案。

这是我的课

public abstract class AThemeableControl<TManager, TControl>
    where TManager:AManagerTheme<TManager, TControl>
    where TControl:AThemeableControl<TManager, TControl>
{
    public abstract void UpdateTheme(TManager managerTheme);
}

这是经理班

public abstract class AManagerTheme<TManager, TControl>
    where TManager:AManagerTheme<TManager, TControl>
    where TControl:AThemeableControl<TManager, TControl>
{
    public TControl[] ThemableControls;

    virtual public void ApplyTheme()
    {
        for (int i = ThemableControls.Length-1; i >= 0; i--)
        {
            ThemableControls[i].UpdateTheme(this); //ERROR HERE           
        }           
    }
}

所以我可以通过类型转换来解决这个错误

ThemableControls[i].UpdateTheme((TManager) this);

但我想知道没有类型转换的解决方案,我希望这是可能的。

标签: c#

解决方案


你不能移除演员表,因为这样做是不安全的。这是演员抛出的示例:

using System;

public abstract class AManagerTheme<TManager, TControl>
    where TManager : AManagerTheme<TManager, TControl>
    where TControl : AThemeableControl<TManager, TControl>
{
    public TControl[] ThemableControls;

    public virtual void ApplyTheme()
    {
        for (int i = ThemableControls.Length - 1; i >= 0; i--)
        {
            ThemableControls[i].UpdateTheme((TManager) this);
        }           
    }
}

public abstract class AThemeableControl<TManager, TControl>
    where TManager : AManagerTheme<TManager, TControl>
    where TControl : AThemeableControl<TManager, TControl>
{
    // Empty implementation; irrelevant for the question.
    public void UpdateTheme(TManager managerTheme) {}
}

public class NormalTheme : AManagerTheme<NormalTheme, NormalControl>
{
}

public class NormalControl : AThemeableControl<NormalTheme, NormalControl>
{
}

public class EvilTheme : AManagerTheme<NormalTheme, NormalControl>
{
}

public class Test
{
    static void Main()
    {
        var theme = new EvilTheme
        {
            ThemableControls = new[] { new NormalControl() }
        };
        theme.ApplyTheme();
    }
}

这是您要防止的:

public class EvilTheme : AManagerTheme<NormalTheme, NormalControl>

...但你不能用 C# 泛型来表达。(我在早期版本的 Protocol Buffers 中遇到过同样的事情,其中​​每个“消息”类型都有相应的“构建器”类型。)C# 类型系统还不够丰富来表达这一点。

您可能想检查抽象类构造函数中的有效性,以便至少您知道强制转换稍后会起作用。但是你不能避免在某处进行投射使用不同的TManager地方。


推荐阅读