Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/apache-kafka/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 这个泛型继承是如何完成的(内部)?_C#_Generics_.net 2.0 - Fatal编程技术网

C# 这个泛型继承是如何完成的(内部)?

C# 这个泛型继承是如何完成的(内部)?,c#,generics,.net-2.0,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 an

你认为下面的代码怎么样?这个好吗?若然,原因为何?若否,原因为何?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>
{
}
公共抽象类EntityBase:IEquatable
{        
公共布尔等于(其他)
{
//检查均衡
}
//是的,下面是对象的Equals和GetHashCode方法实现
}
公共类人员:EntityBase
{
}
我有点奇怪的感觉。比如鸡和蛋的问题。下面是具有相同行为的.Net framework代码

public sealed class String : IComparable<string>, IEquatable<string> // I removed other interfaces
公共密封类字符串:IComparable,IEquatable//我删除了其他接口

有什么想法吗?

在正确的情况下(例如,实施
IComparable
),这正是正确的做法

但这只能在个案的基础上确定,看看为什么会考虑它的细节

P>另一方面,C++允许“好奇的重复基模式”:

模板
类SomeWrapper:T{…]

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

我认为您的代码没有问题。为什么会有问题

关于内部表示,dotNet JIT为每个通用版本编译一个类。因此,如下所示:

class Foo<T> { public T Property; }
Foo<Int> fooint;
Foo<String> foostring;
class Foo{public T Property;}
福福因特;
Foo-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; }
class FooInt{public Int Property;}
类FooString{publicstring属性;}
FooInt FooInt;
FooString FooString;
//这是为以后需要而保留的。
//例如,对于一般铸造,C#4特征。
类Foo{public T Property;}

这不是一个真正的答案,但在我写了这段奇怪的代码之后,我发现这有点道理

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
}
类程序
{
静态void Main(字符串[]参数)
{
var妻子=新人类(性别:女性);
var baby=妻子。分娩();
控制台。书写线(婴儿。性别);
Console.ReadKey();
}
}
类,其中T:new()
{
公营机构
{
}
公共分娩
{
返回新的T();
}
}
类人:Cangivebirtto
{
公共性别{get;私有集;}
公共人权(性别)
{
性别=性别;
}
公共人权()
{
性别=随机分配性别();
}
性别随机性遗传性别()
{
var rand=new Random();
返回(性别)rand.Next(2);
}
}
枚举性别
{
男性=0,
女性=1
}

为了供其他人参考,我复制了的答案(谁在评论中回答)

虽然定义出现了 不是圆形的。但是,C# 编译器循环检测算法 既错又弱。错是因为它 错误地将非周期检测为 循环,因为它不能 检测某些非常恶劣的循环。如果 这个话题让你感兴趣,看我的 关于它的文章如下:


Neat,我不知道你可以这么做:)虽然定义看起来是循环的,但事实并非如此。然而,C#compilers循环检测算法既错误又脆弱。错误是因为它错误地将非循环检测为循环,而脆弱是因为它无法检测某些非常恶劣的循环。如果你对这个主题感兴趣,请参阅我在这里的文章:ps泛型定义中的eudo循环很好。但我担心的是“Person:EntityBase”的关系。我更喜欢我的类型层次结构来模拟现实世界的关系:人是哺乳动物,雇员是人,报纸是出版物,人是“Person的实体库”。这到底是什么意思?@Eric:谢谢你的文章和对“Person:EntityBase”关系的解释。你能提供这些作为答案吗?这样我就可以把你的答案标记为我接受的答案。:)顺便说一句,这种关系应该是“Person:EntityBase,IEquatable”?这是你的意思吗?不,我不是这个意思。如果你和某人谈论长颈鹿,你可能会提到长颈鹿是一种哺乳动物,或一种有蹄类动物,或一种动物,或一种食草动物。但你永远不会说长颈鹿是一种实体。我的意思是“人是一种实体基础“对我来说,它没有任何意义,它没有在现实世界中对人们建模任何东西,因此我认为它是一些难闻的代码。不一定是错误的,而是关切的。”李察:是的,逐个例子。但是,如何思考我的案例?):“SOE:没有足够的细节。需要知道<代码>实体< /代码>与<代码> T < /代码>有关。(这与
this.GetType()
)没有关系。@Richard:谢谢你的回复。我想为每个实体类实现IEquatable。(例如Person)但我不想重复。有趣的部分是类Person:EntityBase。这就是为什么他说这就像鸡和蛋的问题。啊,可能是我,我一直在做荒谬的构造,所以我不认为这是特别的:P.抖动并不是为每个版本编译一个新的。抖动为每个版本编译一个新的,每个版本都有不同的t类型参数_仅当类型参数是值类型时。嗯,真的吗?但这不意味着每次调用Ref类型时都要进行昂贵的转换吗?或者这不是因为指针大小才重要。为什么要进行“昂贵的转换”?你能举个例子说明抖动必须在哪里生成“昂贵的转换”吗?(仅供参考,有些情况下我们必须生成昂贵且不必要的强制转换,但这些情况非常罕见,通常不会出现在真实代码中。我怀疑您正在考虑一些看起来昂贵但实际上很便宜的操作。)
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
}