【问题标题】:Having a master clone method in an abstract class在抽象类中有一个主克隆方法
【发布时间】:2015-10-25 01:52:07
【问题描述】:

我正在使用 ECS 架构,其中 abstractcomponent 类的组件仅使用值类型,从不引用类型。我希望基础 abstractcomponent 类包含 1 和 1 浅拷贝方法,而不必为每个单独的具体类重新实现。

有什么想法吗? C#?

/// <summary>
/// Only an empty classification/tag class. (Every last component is POD -- no exceptions!)
/// </summary>
public abstract class AbstractComponent
{
    public T CreateShallowClone(AbstractComponent c) where T : AbstractComponent
    {
        return (T)c.MemberwiseClone();
    }
}


[Serializable]
public sealed class Entity : Identifiable
{
    public Entity() : base()
    {

    }

    public bool IsEnabled { get; set; } = false;

    private Dictionary<Type, AbstractComponent> Components { get; set; } = new Dictionary<Type, AbstractComponent>();

    public void AddComponent(AbstractComponent c)
    {
        Components.Add(c.GetType(), c);
    }

    public void RemoveComponent<T>() where T : AbstractComponent<T>
    {
        if (!Components.Remove(typeof(T))) {
            throw new KeyNotFoundException();
        }
    }

    public bool HasComponent<T>() where T : AbstractComponent<T>
    {
        if (Components.ContainsKey(typeof(T)))
        {
            return true;
        }
        else
        {
            return false;
        }
    }

    public T GetComponent<T>() where T : AbstractComponent<T>
    {
        AbstractComponent<T> c;
        if (!Components.TryGetValue(typeof(T), out c))
        {
            throw new KeyNotFoundException();
        }
        return c as T;
    }

    public void Destroy()
    {
        Components = null;
    }
}

【问题讨论】:

  • 你能举一个你想做的代码的例子,即使它是错的?
  • public T CreateShallowClone(AbstractComponent c) where T : AbstractComponent { return (T)c.MemberwiseClone(); } } }
  • 请编辑您的帖子并将代码放在那里,它在评论中完全不可读。

标签: c# clone


【解决方案1】:

如果我理解正确,您可以这样使用泛型。

public abstarct class AbstractComponent<TFinalComponent> where TFinalComponent : AbstractComponent<TFinalComponent> {
    public TFinalComponent CreateShallowClone() {
        return (TFinalComponent)this.MemberwiseClone();
    }
}

编辑: 现在我终于从您的源代码中看到了重点。 泛型是不必要的。没有它们,一切都可以完成。

public abstract class AbstractComponent {
    public AbstractComponent CreateShallowClone() {
        return (AbstractComponent)this.CreateShallowClone();
    }
}

public sealed class MyCustomComponent : AbstractComponent {
    public string Name { get; set; }
    public int Age { get; set; }
}

public sealed class Entity {
    public bool IsEnabled { get; set; }
    private Dictionary<Type, AbstractComponent> components = new Dictionary<Type, AbstractComponent>();

    public void AddComponent(AbstractComponent component) {
        if (null == component) { throw new ArgumentNullException("component"); }

        this.components.Add(component.GetType(), component);
    }
    public bool RemoveComponent(Type componentType) {
        if (null == componentType) { throw new ArgumentNullException("componentType"); }

        return this.components.Remove(componentType);
    }
    public bool HasComponent(Type componentType) {
        if (null == componentType) { throw new ArgumentNullException("componentType"); }

        return this.components.ContainsKey(componentType);
    }
    public AbstractComponent FindComponent(Type componentType) {
        if (null == componentType) { throw new ArgumentNullException("componentType"); }

        AbstractComponent result;
        this.components.TryGetValue(componentType, out result);
        return result;
    }
    public AbstractComponent GetComponent(Type componentType) {
        if (null == componentType) { throw new ArgumentNullException("componentType"); }

        var result = this.FindComponent(componentType);
        if (null == result) {
            throw new ArgumentException("The component of the specified type was not found.", "componentType");
        }

        return result;
    }
    public TComponent GetComponent<TComponent>() where TComponent : AbstractComponent {
        return (TComponent)this.GetComponent(typeof(TComponent));
    }

    public void Destroy() {
        this.components.Clear();
    }

    public Entity Clone() {
        var result = new Entity();
        foreach (var item in this.components.Values) {
            var clonedItem = item.CreateShallowClone();
            result.AddComponent(item);
        }

        return result;
    }
}

一些注意事项:

  • 方法RemoveComponent()不需要泛型,一般来说最好有非泛型方法(如果你可以选择),因为调用者在编译时不需要知道具体类型
  • 方法RemoveComponent() 在组件不存在时不需要抛出异常。两种情况的结果都是一样的 - 组件不会出现在实体中
  • 可以使用方法FindComponent() 代替调用HasComponent()GetComponent。这对性能更好。
  • 方法GetComponent()被重载

    • 一个重载是非泛型的,原因与RemoveComponent() 方法相同。
    • 一个重载是通用的,以便在代码中更好地使用:

    var custom = entity.GetComponent();

    • 方法`Destroy()' 只是清除组件。它比设置 null 更好,因为该类的用户无法知道实例是否被“销毁”,并且对这些实体的任何调用都会导致异常。

【讨论】:

  • 我有一个包含组件列表的实体类,我希望克隆实体本身。我将如何遍历该列表并单独克隆每个列表?
  • 请详细说明“实体类”和“组件列表”。
  • 你去。我仍然遇到泛型问题。 :(
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-10-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-04-10
  • 1970-01-01
相关资源
最近更新 更多