如何在C#中编写这样的类?

如何在C#中编写这样的类?,c#,.net,code-generation,code-duplication,C#,.net,Code Generation,Code Duplication,我在一个项目中有多个完全相同的类,除了类的名称。基本上,它们表示运行时从配置文件加载的美化枚举。这些类如下所示: public class ClassName : IEquatable<ClassName> { public ClassName(string description) { Description = description; } public override bool Equals(object obj) {

我在一个项目中有多个完全相同的类,除了类的名称。基本上,它们表示运行时从配置文件加载的美化枚举。这些类如下所示:

public class ClassName : IEquatable<ClassName> {
    public ClassName(string description) {
        Description = description;
    }

    public override bool Equals(object obj) {
        return obj != null &&
            typeof(ClassName).IsAssignableFrom(obj.GetType()) && 
            Equals((ClassName)obj);
    }

    public bool Equals(ClassName other) {
        return other != null && 
            Description.Equals(other.Description);
    }

    public override int GetHashCode() {
        return Description.GetHashCode();
    }

    public override string ToString() {
        return Description;
    }

    public string Description { get; private set; }
}
public class ClassName1 : MyBase<ClassName1> { ... }
public class ClassName2 : MyBase<ClassName2> { ... }
public class ClassName3 : MyBase<ClassName3> { ... }
公共类类名:IEquatable{
公共类名(字符串描述){
描述=描述;
}
公共覆盖布尔等于(对象对象对象){
返回对象!=null&&
typeof(ClassName).IsAssignableFrom(obj.GetType())&&
等于((类名)obj);
}
公共布尔等于(类名称其他){
返回其他!=null&&
Description.Equals(其他.Description);
}
公共覆盖int GetHashCode(){
返回Description.GetHashCode();
}
公共重写字符串ToString(){
返回说明;
}
公共字符串说明{get;private set;}
}

我认为没有理由复制这个文件并多次更改类名。当然,有一种方法我可以列出我想要的类,并让它们自动为我创建。如何?

您考虑过了吗?

您考虑过了吗?

我建议您自己创建代码片段,这将是快速而简单的。

我建议您自己创建代码片段,这将是快速而简单的。

我建议使用T4。与代码片段相比,这种方法的一个重要优点是,如果更改模板,则所有代码都将更新以匹配

将其放入扩展名为
.tt

<#@ template language="C#" #>
<#@ output extension=".codegen.cs" #>
<#@ assembly name="System.dll" #>
<#@ import namespace="System" #>
// <auto-generated>
// This code was generated by a tool. Any changes made manually will be lost
// the next time this code is regenerated.
// </auto-generated>

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace MyStuff
{
<# foreach (string classname in classes) {#>
    public class <#= classname #> : IEquatable<ClassName> 
    {
            public <#= classname #>(string description) {
        Description = description;
    }

    public override bool Equals(object obj) {
        return obj != null &&
            typeof(<#= classname #>).IsAssignableFrom(obj.GetType()) && 
            Equals((<#= classname #>)obj);
    }

    public bool Equals(<#= classname #>other) {
        return other != null && 
            Description.Equals(other.Description);
    }

    public override int GetHashCode() {
        return Description.GetHashCode();
    }

    public override string ToString() {
        return Description;
    }

    public string Description { get; private set; }
    }
    }

<# } #> 
}

<#+ string[] classes = new string[] {  "Class1",
                                       "Class2" };
#>

// 
//这段代码是由一个工具生成的。手动所做的任何更改都将丢失
//下次重新生成此代码时。
// 
使用制度;
使用System.Collections.Generic;
使用System.Linq;
使用系统文本;
名称空间MyStuff
{
公共类:IEquatable
{
公共(字符串描述){
描述=描述;
}
公共覆盖布尔等于(对象对象对象){
返回对象!=null&&
typeof().IsAssignableFrom(obj.GetType())&&
等于(()obj);
}
公共布尔等于(其他){
返回其他!=null&&
Description.Equals(其他.Description);
}
公共覆盖int GetHashCode(){
返回Description.GetHashCode();
}
公共重写字符串ToString(){
返回说明;
}
公共字符串说明{get;private set;}
}
}
}

VS将为您生成一个源文件。需要新类时,只需添加到数组
类即可。

我建议使用T4。与代码片段相比,这种方法的一个重要优点是,如果更改模板,则所有代码都将更新以匹配

将其放入扩展名为
.tt

<#@ template language="C#" #>
<#@ output extension=".codegen.cs" #>
<#@ assembly name="System.dll" #>
<#@ import namespace="System" #>
// <auto-generated>
// This code was generated by a tool. Any changes made manually will be lost
// the next time this code is regenerated.
// </auto-generated>

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace MyStuff
{
<# foreach (string classname in classes) {#>
    public class <#= classname #> : IEquatable<ClassName> 
    {
            public <#= classname #>(string description) {
        Description = description;
    }

    public override bool Equals(object obj) {
        return obj != null &&
            typeof(<#= classname #>).IsAssignableFrom(obj.GetType()) && 
            Equals((<#= classname #>)obj);
    }

    public bool Equals(<#= classname #>other) {
        return other != null && 
            Description.Equals(other.Description);
    }

    public override int GetHashCode() {
        return Description.GetHashCode();
    }

    public override string ToString() {
        return Description;
    }

    public string Description { get; private set; }
    }
    }

<# } #> 
}

<#+ string[] classes = new string[] {  "Class1",
                                       "Class2" };
#>

// 
//这段代码是由一个工具生成的。手动所做的任何更改都将丢失
//下次重新生成此代码时。
// 
使用制度;
使用System.Collections.Generic;
使用System.Linq;
使用系统文本;
名称空间MyStuff
{
公共类:IEquatable
{
公共(字符串描述){
描述=描述;
}
公共覆盖布尔等于(对象对象对象){
返回对象!=null&&
typeof().IsAssignableFrom(obj.GetType())&&
等于(()obj);
}
公共布尔等于(其他){
返回其他!=null&&
Description.Equals(其他.Description);
}
公共覆盖int GetHashCode(){
返回Description.GetHashCode();
}
公共重写字符串ToString(){
返回说明;
}
公共字符串说明{get;private set;}
}
}
}

VS将为您生成一个源文件。当您需要一个新类时,只需将类添加到数组中。

如果这些类确实完全相同,您是否可以使用继承?代码量非常小,不需要任何额外的前/后处理

public class Equatable : IEquatable { ... }

public class ClassName1 : Equatable {}
public class ClassName2 : Equatable {}
public class ClassName3 : Equatable {}
public class ClassName4 : Equatable {}

注意:如果您需要更改某些内容,所有代码片段建议似乎都会成为维护过程中的噩梦。

如果类确实完全相同,您是否可以使用继承?代码量非常小,不需要任何额外的前/后处理

public class Equatable : IEquatable { ... }

public class ClassName1 : Equatable {}
public class ClassName2 : Equatable {}
public class ClassName3 : Equatable {}
public class ClassName4 : Equatable {}

注意:如果您需要更改某些内容,所有代码段建议似乎都会成为维护过程中的噩梦。

您能将继承与泛型结合使用吗

public class MyBase<T> : IEquatable<MyBase<T>>
    where T : MyBase
{
    public ClassName(string description) {
        Description = description;
    }

    public override bool Equals(object obj) { ... }

    public bool Equals(T other) {
        return other != null && 
            Description.Equals(other.Description);
    }

    public override int GetHashCode() { ... }

    public override string ToString() { ... }

    public string Description { get; private set; }
}
公共类MyBase:IEquatable
其中T:MyBase
{
公共类名(字符串描述){
描述=描述;
}
公共覆盖布尔等于(对象对象对象){…}
公共布尔等于(T其他){
返回其他!=null&&
Description.Equals(其他.Description);
}
公共重写int GetHashCode(){…}
公共重写字符串ToString(){…}
公共字符串说明{get;private set;}
}
然后你可以像这样继承:

public class ClassName : IEquatable<ClassName> {
    public ClassName(string description) {
        Description = description;
    }

    public override bool Equals(object obj) {
        return obj != null &&
            typeof(ClassName).IsAssignableFrom(obj.GetType()) && 
            Equals((ClassName)obj);
    }

    public bool Equals(ClassName other) {
        return other != null && 
            Description.Equals(other.Description);
    }

    public override int GetHashCode() {
        return Description.GetHashCode();
    }

    public override string ToString() {
        return Description;
    }

    public string Description { get; private set; }
}
public class ClassName1 : MyBase<ClassName1> { ... }
public class ClassName2 : MyBase<ClassName2> { ... }
public class ClassName3 : MyBase<ClassName3> { ... }
public类ClassName1:MyBase{…}
公共类ClassName2:MyBase{…}
公共类ClassName3:MyBase{…}

您可以将继承与泛型一起使用吗

public class MyBase<T> : IEquatable<MyBase<T>>
    where T : MyBase
{
    public ClassName(string description) {
        Description = description;
    }

    public override bool Equals(object obj) { ... }

    public bool Equals(T other) {
        return other != null && 
            Description.Equals(other.Description);
    }

    public override int GetHashCode() { ... }

    public override string ToString() { ... }

    public string Description { get; private set; }
}
公共类MyBase:IEquatable
其中T:MyBase
{
公共类名(字符串描述){
描述=描述;
}
公共覆盖布尔等于(对象对象对象){…}
公共布尔等于(T其他){
返回其他!=null&&
Description.Equals(其他.Description);
}
公共重写int GetHashCode(){…}
公共重写字符串ToString(){…}
公共字符串说明{get;private set;}
}
然后你可以像这样继承:

public class ClassName : IEquatable<ClassName> {
    public ClassName(string description) {
        Description = description;
    }

    public override bool Equals(object obj) {
        return obj != null &&
            typeof(ClassName).IsAssignableFrom(obj.GetType()) && 
            Equals((ClassName)obj);
    }

    public bool Equals(ClassName other) {
        return other != null && 
            Description.Equals(other.Description);
    }

    public override int GetHashCode() {
        return Description.GetHashCode();
    }

    public override string ToString() {
        return Description;
    }

    public string Description { get; private set; }
}
public class ClassName1 : MyBase<ClassName1> { ... }
public class ClassName2 : MyBase<ClassName2> { ... }
public class ClassName3 : MyBase<ClassName3> { ... }
public类ClassName1:MyBase{…}
公共类ClassName2:MyBase{…}
公共类ClassName3:MyBase{…}

为什么普通的类继承不起作用?那么你唯一要重复的就是c