这个通用继承是如何完成的(内部)?

时间:2009-07-13 08:14:26

标签: c# generics .net-2.0

您如何看待以下代码?这个好吗?如果是这样,为什么呢?如果不是,为什么不呢? CLR如何看到这段代码?

public abstract class EntityBase<TEntity> : IEquatable<TEntity>
{        
    public bool Equals(TEntity other)
    {
        // check equalitiy
    }

    // yes, below is object's Equals and GetHashCode method implementation
}

public class Person : EntityBase<Person>
{
}

我对此有点奇怪的感觉。喜欢鸡肉和鸡蛋的问题。这里是.Net框架代码,具有相同的行为。

public sealed class String : IComparable<string>, IEquatable<string> // I removed other interfaces

有什么想法吗?

4 个答案:

答案 0 :(得分:2)

在适当的情况下(例如实施IComparable<T>),这是正确的做法。

但这只能根据具体情况确定,并详细考虑其原因。

另一方面,C ++允许“奇怪的重复基础模式”:

template<typename T>
class SomeWrapper<T> : T { ... ]

其中泛型类继承其通用包装器。这允许一些高级包装方案,但如果在包装之外使用,可能会快速变得混乱。幸运的是(?).NET中不允许使用这种模式。

答案 1 :(得分:1)

不是一个真正的答案,但在我写完这个奇怪的代码后,我发现它有点意义......

class Program
{
    static void Main(string[] args)
    {
        var wife = new Human(Gender.Female);
        var baby = wife.GiveBirth();
        Console.WriteLine(baby.Gender);

        Console.ReadKey();
    }
}

class CanGiveBirthTo<T> where T : new()
{
    public CanGiveBirthTo()
    {
    }

    public T GiveBirth()
    {
        return new T();
    }
}

class Human : CanGiveBirthTo<Human>
{
    public Gender Gender { get; private set; }

    public Human(Gender gender)
    {
        Gender = gender;
    }

    public Human()
    {
        Gender = RandomlyAssignAGender();
    }

    Gender RandomlyAssignAGender()
    {
        var rand = new Random();
        return (Gender) rand.Next(2);
    }
}

enum Gender
{
    Male = 0,
    Female = 1
}

答案 2 :(得分:0)

我发现您的代码没有问题。为什么会出问题呢?

关于内部表示,dotNet JIT为每个通用版本编译一个类。以下是:

class Foo<T> { public T Property; }
Foo<Int> fooint;
Foo<String> foostring;

有点编译成:

class FooInt { public Int Property; } 
class FooString { public String Property; }
FooInt fooint;
FooString foostring;
// This is kept for if it is needed later.
// For example for generic casting, a C#4 feature.
class Foo<T> { public T Property; }

答案 3 :(得分:0)

对于其他人的参考,我复制了Eric Lippert的答案(在评论中回答)。

  

虽然出现了定义   循环,它不是。但是,C#   编译器循环检测算法是   既错又弱。错了,因为它   错误地将非循环检测为   循环,因为它没有失败   检测某些非常讨厌的周期。如果   这个话题让你感兴趣,看看我的   文章在这里:   http://blogs.msdn.com/ericlippert/archive/2008/05/07/covariance-and-contravariance-part-twelve-to-infinity-but-not-beyond.aspx