简体   繁体   English

在抽象类中具有主克隆方法

[英]Having a master clone method in an abstract class

I am using an ECS architecture where components of the abstractcomponent class use value types only, and never reference types. 我使用的是ECS架构,其中的abstractcomponent类使用价值种成分而已, 从来没有引用类型。 I would like for the base abstractcomponent class to contain 1 and 1 shallowcopy method without having to reimplement that for each individual concrete class. 我希望基本abstractcomponent类包含1和1浅表复制方法,而不必为每个具体的类重新实现。

ANy ideas? 有任何想法吗? C#? 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;
    }
}

If I understand right, you can use generics this way. 如果我理解正确,则可以通过这种方式使用泛型。

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

EDIT: Now I finally see the point from your source code. 编辑:现在,我终于从您的源代码中看到了重点。 The generics are unnecessary. 泛型是不必要的。 All can be done without them. 没有他们,所有事情都可以完成。

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;
    }
}

Some notes: 一些注意事项:

  • method RemoveComponent() does not need generics, generaly it's better to have non-generic methods (if you can choose) because caller does not need know concrete type before compile-time 方法RemoveComponent()不需要泛型,通常最好有非泛型方法(如果可以选择),因为调用者在编译时不需要知道具体类型
  • method RemoveComponent() does not need throw exception when component was not present. 当组件不存在时,方法RemoveComponent()不需要引发异常。 the result will be same for both cases - the component will be not present in the entity 两种情况的结果都是相同的-该组件将不存在于实体中
  • method FindComponent() can be used instead of calling HasComponent() and GetComponent . 可以使用方法FindComponent()代替调用HasComponent()GetComponent it's better for perfofmance. 对于性能而言更好。
  • method GetComponent() is overloaded 方法GetComponent()已重载

    • one overload is non-generic for same reasons like RemoveComponent() method. 由于类似的原因,一个重载是非泛型的,例如RemoveComponent()方法。
    • one overload is generic for better usage in code: 一种重载是通用的,可以在代码中更好地使用:

    var custom = entity.GetComponent(); var custom = entity.GetComponent();

    • method `Destroy()' just clear the components. 方法“ Destroy()”只是清除组件。 it's better than setting that null because user of the class does not have any way how to know if the instance is "destroyed" and any call on these entity will cause exception. 最好将其设置为null,因为该类的用户无法知道实例是否被“破坏”,并且对这些实体的任何调用都会导致异常。

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

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