Amaçlarım için, @ T-moty'nin fikrini beğendim. Yıllardır "kendi kendine referans veren tip" bilgisini kullanmış olsam da, temel sınıfa atıfta bulunmak daha sonra daha zor.
Örneğin (yukarıdaki @Rob Leclerc örneğini kullanarak):
public class ChildA: Parent<ChildA>
{
}
public class ChildB: Parent<ChildB>
{
}
Bu modelle çalışmak zor olabilir, örneğin; temel sınıfı bir işlev çağrısından nasıl döndürürsünüz?
public Parent<???> GetParent() {}
Veya tip döküm ne zaman?
var c = (Parent<???>) GetSomeParent();
Bu yüzden, elimden geldiğince kaçınmaya çalışıyorum ve gerektiğinde kullanıyorum. Gerekirse, şu kalıbı izlemenizi öneririm:
class BaseClass
{
public int Id { get; private set; }
public string Name { get; private set; }
public void Run() {}
}
class BaseClass<TSelfReferenceType> : BaseClass
{
public TSelfReferenceType Foo() {}
public void Bar(TSelfRefenceType obj) {}
}
Artık (daha fazla) ile kolayca çalışabilirsiniz BaseClass
. Bununla birlikte, benim mevcut durumum gibi, türetilmiş sınıfı temel sınıf içinden açığa çıkarmanın gerekli olmadığı ve @ M-moty'nin önerisini kullanmanın doğru yaklaşım olabileceği zamanlar vardır.
Ancak, @ M-moty'nin kodunu kullanmak, yalnızca temel sınıf çağrı yığınında herhangi bir örnek oluşturucu içermediği sürece çalışır. Maalesef benim temel sınıflarım örnek oluşturucuları kullanıyor.
Bu nedenle, temel sınıf 'örnek' oluşturucularını hesaba katan benim genişletme yöntemim:
public static class TypeExtensions
{
public static Type GetDrivedType(this Type type, int maxSearchDepth = 10)
{
if (maxSearchDepth < 0)
throw new ArgumentOutOfRangeException(nameof(maxSearchDepth), "Must be greater than 0.");
const int skipFrames = 2;
var stack = new StackTrace();
var maxCount = Math.Min(maxSearchDepth + skipFrames + 1, stack.FrameCount);
var frame = skipFrames;
while (frame < maxCount)
{
var method = stack.GetFrame(frame).GetMethod();
var declaringType = method.DeclaringType;
if (type.IsAssignableFrom(declaringType))
return declaringType;
frame++;
}
return null;
}
}