泛型 类 中具有继承的 C# 方法链接
C# method-chaining in generic classes with inheritance
我有 class A 和 class 继承自 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<A> a1 = new List<A> { b1, b2, c1};
行不工作。它写了一个错误,我需要使用泛型类型 A,但当我尝试编写它时它是一个无限递归类型。你能以某种方式帮助我吗?谢谢!
您的 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<IA>
并将其传递给此方法。
请注意,现在您丢失了 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");
我有 class A 和 class 继承自 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<A> a1 = new List<A> { b1, b2, c1};
行不工作。它写了一个错误,我需要使用泛型类型 A,但当我尝试编写它时它是一个无限递归类型。你能以某种方式帮助我吗?谢谢!
您的 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<IA>
并将其传递给此方法。
请注意,现在您丢失了 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");