简体   繁体   English

在父方法中返回子类型的通用方法

[英]Generic method to return a child type in a parent method

I've been experimenting extension methods in C# for a few weeks and I've come across something interesting. 我已经在C#中尝试了扩展方法几周,并且遇到了一些有趣的事情。 I've experimented building generics for my DTOs like so: 我已经尝试过为DTO构建泛型,如下所示:

public class ParentDto{
    public string attrStr{get;set;}
}

public static class ParentDtoExtensions{
    public static T AttrStr<T>(this T parentDto, string attrStr)
    where T:ParentDto{
        parentDto.attrStr = attrStr;
        return parentDto;
    }
}

And then in the child class: 然后在子类中:

public class ChildDto:ParentDto{
    public string childAttrStr{get;set;}
}

public static class ChildDtoExtensions{
    public static T ChildAttrStr<T>(this T childDto, string childAttrStr)
    where T:ChildDto{
        childDto.childAttrStr = childAttrStr;
        return childDto;
    }
} 

Which then lets me chain my methods like so: 然后让我像这样链接我的方法:

return ((new ChildDto()).AttrStr("someString").ChildAttrStr("someOtherString"));

Which really appeals to me. 这真的吸引了我。 Being able to have the monad-ish setters as well as other methods return the calling type is very convenient for chaining a block of code. 能够使用monad-ish setter以及其他方法返回调用类型对于链接代码块非常方便。

However, I would love to be able to integrate the setter methods into the parent class where I believe they truly belong, while maintaining the existing code flow shown above, but I'm not aware of a way to implement a method that returns a child class of the implementing class. 但是,我希望能够将setter方法集成到我认为它们真正所属的父类中,同时保持上面显示的现有代码流,但是我不知道实现返回孩子的方法的方法。实现类的类。 Something like: 就像是:

public class ParentDto{
    public string attrStr{get;set;}

    public T AttrStr<T>(string attrStr)
    where T:ParentDto{
        parentDto.attrStr = attrStr;
        return parentDto;
    }
}

But this doesnt work on account of the compiler (?) not knowing the calling type. 但这对编译器(?)不起作用,因为它不知道调用类型。 Does anyone know how to do this? 有谁知道如何做到这一点?

Please keep in mind I'm not looking for advice on code smell of my existing implementation, as I'm sure there are more C# -ish ways to implement this. 请记住,我不是在寻求有关现有实现的代码味道的建议,因为我敢肯定有更多的C#方式可以实现此目的。

You could do something like the following, but IMO your extension methods are much better: 您可以执行以下操作,但是IMO的扩展方法要好得多:

public class ParentDto<T> where T : ParentDto<T> {
    public string attrStr{get;set;}

    public T AttrStr(string attrStr) {
        this.attrStr = attrStr;
        return (T)this;
    }
}
public sealed class ChildDto : ParentDto<ChildDto> {
    public string childAttrStr{get;set;}
    public ChildDto ChildAttrStr(string childAttrStr) {
        this.childAttrStr = childAttrStr;
        return this;
    }
}

For more on this pattern and why you should avoid it when possible, see Eric Lippert's blog post, Curiouser and curiouser . 有关此模式的更多信息以及为什么应尽可能避免使用它,请参阅Eric Lippert的博客文章Curiouser and curiouser

That said, I agree that this is a code smell; 就是说,我同意这是一种代码味道。 you should probably just use the property setters instead of a fluent syntax. 您应该只使用属性设置器,而不要使用流利的语法。 But since you're not asking for advice there, I'll leave it at that. 但是,由于您不在那里寻求建议,因此我将保留它。

If all you're doing is setting properties on a new object then you could use an object initializer to do this instead: 如果您要做的只是在新对象上设置属性,则可以使用对象初始化程序来代替:

return new ChildDto()
    {
        attrStr = "someString",
        childAttrString = "someOtherString"
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM