【问题标题】:C# method-chaining in generic classes with inheritance具有继承的泛型类中的 C# 方法链
【发布时间】:2021-06-24 16:52:54
【问题描述】:

我有从 A 继承的 A 类和 B 类和 C 类。 我试图像这样实现它们:

public static class Extension
    {
        public static List<T> WithYchangeByX<T>(this List<T> list, string firstX, string newY) where T : A<T>
        {
            for (int i = 0; i < list.Count; i++)
            {
                if (list[i].X.Split(' ')[0].Equals(firstX))
                {
                    list[i] = list[i].WithY(newY);
                }
            }
            return list;
        }
    }

    public abstract class A<T> where T : A<T>
    {
        public string X { get; }
        public string Y { get; }

        abstract public T WithX(string x);

        abstract public T WithY(string y);
    }

    class B: A<B>
    {
        public new string X { get; }
        public new string Y { get; }
        public DateTime Bspecial { get; }
        public static B Default { get; }

        public B(string x, string y, DateTime bSpecial)
            => (X, Y, Bspecial) = (x, y, bSpecial);

        override public B WithX(string x)
            => new B(x, this.Y, this.Bspecial);

        override public B WithY(string y)
            => new B(this.X, y, this.Bspecial);

        public B WithBspecial(DateTime bSpecial)
            => new B(this.X, this.Y, bSpecial);
    }

    class C: A<C>
    {
        public new string X { get; }
        public new string Y { get; }
        public int Cspecial { get; }
        public static C Default { get; }

        public C(string x, string y, int cSpecial)
            => (X, Y, Cspecial) = (x, y, cSpecial);

        override public C WithX(string x)
            => new C(x, this.Y, this.Cspecial);

        override public C WithY(string y)
            => new C(this.X, y, this.Cspecial);

        public C WithCspecial(int cSpecial)
            => new C(this.X, this.Y, cSpecial);
    }

我需要这段代码才能工作:

var b1 = B.Default.WithX("string").WithY("string").WithBspecial(new DateTime(2000, 1, 28));
var b2 = B.Default.WithX("string").WithY("string").WithBspecial(new DateTime(2000, 1, 17));
var c1 = C.Default.WithX("string").WithY("string").WithCspecial(5);

List<A> a1 = new List<A> { b1, b2, c1};

var a2 = a1.WithYchangeByX(x: "string", y: "string");

一切正常,只有List&lt;A&gt; a1 = new List&lt;A&gt; { b1, b2, c1}; 行不工作。它写了一个错误,我需要使用泛型类型 A,但是当我尝试编写它时它是一个无限递归类型。你能以某种方式帮助我吗?谢谢!

【问题讨论】:

  • 请注意,C 中有一个复制粘贴错误。

标签: c# generics inheritance extension-methods method-chaining


【解决方案1】:

您的WithYchangeByX 方法实际上并不太关心泛型参数T,因此您可以引入一个非泛型接口IA,并使其与它一起工作:

public interface IA
{
    string X { get; }
    string Y { get; }
    IA WithX(string x);
    IA WithY(string y);
}

public abstract class A<T> : IA where T : A<T>
{
    public string X { get; }
    public string Y { get; }

    abstract public T WithX(string x);

    abstract public T WithY(string y);

    IA IA.WithX(string x) => WithX(x);

    IA IA.WithY(string y) => WithY(y);
}

那么你可以这样做:

public static List<IA> WithYchangeByX(this List<IA> list, string firstX, string newY)
{
    for (int i = 0; i < list.Count; i++)
    {
        if (list[i].X.Split(' ')[0].Equals(firstX))
        {
            list[i] = list[i].WithY(newY);
        }
    }
    return list;
}

然后您可以创建一个List&lt;IA&gt; 并将其传递给此方法。

请注意,现在您丢失了WithYchangeByXImpl 的通用版本。如果你想保留它,你可以这样做:

private static List<T> WithYchangeByXImpl<T>(List<T> list, string firstX, string newY, Action<int, List<T>> consumer) where T: IA
{
    for (int i = 0; i < list.Count; i++)
    {
        if (list[i].X.Split(' ')[0].Equals(firstX))
        {
            consumer(i, list);
        }
    }
    return list;
}

// these look to be the same, but they actually infer a different type parameter for WithYchangeByXImpl
public static List<IA> WithYchangeByX(this List<IA> list, string firstX, string newY)
    => WithYchangeByXImpl(list, firstX, newY, (i, list) => list[i] = list[i].WithY(newY));

public static List<T> WithYchangeByX<T>(this List<T> list, string firstX, string newY) where T: A<T>
    => WithYchangeByXImpl(list, firstX, newY, (i, list) => list[i] = list[i].WithY(newY));

现在这段代码可以编译了:

var b1 = B.Default.WithX("string").WithY("string").WithBspecial(new DateTime(2000, 1, 28));
var b2 = B.Default.WithX("string").WithY("string").WithBspecial(new DateTime(2000, 1, 17));
var c1 = C.Default.WithX("string").WithY("string").WithCspecial(5);

List<IA> a1 = new List<IA> { b1, b2, c1 };

var a2 = a1.WithYchangeByX("string", "string");

【讨论】:

  • 非常感谢! :)
猜你喜欢
  • 2020-05-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多