在抽象类

时间:2015-10-25 01:52:08

标签: c# clone

我使用的是ECS架构,其中abstractcomponent类的组件仅使用值类型,而 never 引用类型。我希望base abstractcomponent类包含1和1个shallowcopy方法,而不必为每个具体类重新实现。

任何想法? 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;
    }
}

1 个答案:

答案 0 :(得分: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。对于perfofmance来说,它更好。
  • 方法GetComponent()已超载

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

    var custom = entity.GetComponent();

    • 方法`Destroy()&#39;只需清除组件。它比设置null更好,因为类的用户没有任何方法知道实例是否被&#34;销毁&#34;对这些实体的任何调用都会导致例外。