C# 在C中链接方法时如何强制转换#

C# 在C中链接方法时如何强制转换#,c#,syntax,casting,C#,Syntax,Casting,我试图编写一些代码,我总是返回对象本身,以便继续链接。像这样 object.SetThis().SetThat().SetThisThirdThing().setThisFourthThing(); 我在我所有的方法中都返回了这个,所以我可以继续这样做。但是我的一个方法是我在基类中创建的,它当然会返回基类 因此,它返回的不是public MyClass SetThat(),而是public超类SetThat()。因为它返回的是SuperClass而不是MyClass,所以我不能调用setThi

我试图编写一些代码,我总是返回对象本身,以便继续链接。像这样

object.SetThis().SetThat().SetThisThirdThing().setThisFourthThing();
我在我所有的方法中都返回了这个,所以我可以继续这样做。但是我的一个方法是我在基类中创建的,它当然会返回基类

因此,它返回的不是
public MyClass SetThat()
,而是
public超类SetThat()
。因为它返回的是
SuperClass
而不是
MyClass
,所以我不能调用
setThistThirdThing()
,因为基类不知道它

那么我该如何铸造它,这样我才能保留链子呢?语法是什么?我试过了

object.SetThis().(MyClass)SetThat().SetThisThirdThing().setThisFourthThing();
或者有没有一种方法可以让超类方法在从子类调用时返回子类,而不必在所有子类中重写它

这是所有子类的共同点之一,因此如果我能够以某种方式绕过它,而不必在所有子类中重写它,那将是非常好的

var obj = ((MyType)myObject.SetThis()).SetThat();
另外,你应该避免这样做,因为读起来会很混乱。

只需使用括号:

(MyClass)(object.SetThis().SetThat()).SetThisThirdThing().setThisFourthThing();
我不知道为什么
对象在那里,但您可以安全地将其删除

(MyClass)(SetThis().SetThat()).SetThisThirdThing().setThisFourthThing();
试着这样做:

((MyClass)object.SetThis().SetThat()).SetThisThirdThing()
有没有办法让超类方法在从子类调用时返回子类,而不必在所有子类中重写它

你能使超类通用吗

public class SuperClass<T> where T: SuperClass<T>
{
    public T SetThis()
    {
        ....
        return (T)this;
    }
}

public class SubClass : SuperClass<SubClass>
{
}
公共类超类,其中T:SuperClass
{
公共T SetThis()
{
....
返回(T)这个;
}
}
公共类子类:超类
{
}
请注意,这不是100%保证,因为您也可以这样做:

public class EvilSubClass : SuperClass<SubClass>
{
}
公共类子类:超类
{
}
它符合一般限制条件,但现在
SetThis()
的返回类型是
SubClass
,而不是
SubClass

要强制转换(sub)表达式,需要将类名放在前面(并使用括号)

(请注意,
object
是保留字,因此不能将其用作变量名)

另一种方法是使用关键字:

请注意,如果
setThat()
不返回
MyClass
,则这将有不同的行为;
第一个版本将抛出一个
InvalidCastException
,第二个版本抛出一个
NullReferenceException
,因为
as
返回
null
,如果不能进行强制转换。

在不修改类的情况下,您也可以像这样编写扩展方法

public static T As<T>(this MyBaseClass obj) where T : MyBaseClass
{
   return (T)obj;
}
publicstatict-As(这个MyBaseClass对象),其中T:MyBaseClass
{
返回(T)obj;
}
--

用法与此类似

new MyChildClass().SetBase().As<MyChildClass>().SetThis();
newmychildclass().SetBase().As().SetThis();

为什么不这样做?一个简单的
Cast
方法可以帮助您将其转换回正确的类型

class Program
{
    static void Main(string[] args)
    {
        var obj = new MyClass();
        //obj.SetThis().SetThat().SetThisThirdThing().setThisFourthThing(); // Compile error
        obj.SetThis().SetThat().Cast<MyClass>().SetThisThirdThing().setThisFourthThing();
    }
}

class SuperClass
{
    public SuperClass SetThat()
    {
        return this;
    }

    public T Cast<T>() where T : SuperClass
    {
        return (T)this;
    }
}

class MyClass : SuperClass
{
    public MyClass SetThis()
    {
        return this;
    }

    public MyClass SetThisThirdThing()
    {
        return this;
    }

    public MyClass setThisFourthThing()
    {
        return this;
    }
}
类程序
{
静态void Main(字符串[]参数)
{
var obj=新的MyClass();
//obj.SetThis().SetThis().SetThisThirdThing().setThisFourthThing();//编译错误
obj.SetThis().SetThis().Cast().SetThisThirdThing().setThisFourthThing();
}
}
类超类
{
公共超类SetThat()
{
归还这个;
}
公共T Cast(),其中T:超类
{
返回(T)这个;
}
}
类MyClass:超类
{
公共MyClass SetThis()
{
归还这个;
}
公共MyClass设置此第三项()
{
归还这个;
}
公共MyClass设置第四个()
{
归还这个;
}
}


为什么不直接强制转换第一个元素?((MyClass)object).SetThis().SetThat()作为参考,“dotting”通常被称为“fluent interface”。@Mitch不确定这是真的,fluent interface实际上只是
方法链接的一个子集
很有趣,但不要这样做。下周你会回顾这段代码,想知道你到底在做什么。从逻辑上讲,这是两种不同的操作。使用多个语句。@PhilippeParé因为
SetThat
返回
SuperClass
,而这正是他们想要的。Parhaps进一步解释了为什么应该避免这种情况。@Paulch先生认为这是显而易见的:)对你来说是显而易见的,对我来说可能也是显而易见的。但不是每个人都清楚。这只是一个改进你答案的建议!我相信OP想要投射的是
SetThat
的结果,而不是
SetThis
的结果。该对象只是显示我在一个对象上执行该操作。也可能是myObject。SetThis()。SetThis()
object
是变量名。但是,我确实喜欢额外的括号,这使它非常明显地显示了正在进行的转换。但是,如果您将
用作MyClass
,您可以得到空引用异常。在相同的场景中,如果您使用直接转换,您只会得到一个不同的异常。我认为这是解决我的困境的一个极好的解决方案。我就试试这个。这个似乎很好用,所以我会接受它作为答案。但是现在我有一个问题,我想把泛型超类作为方法参数。我不能只使用public MySuperClass addThis(MySuperClass theObject),因为它说“名称MySuperClass在当前上下文中不存在”?如何解决此问题?:)我会把它作为一个单独的问题来问——但大体上你可以把非泛型方法分成一个非泛型超类。但这取决于您打算如何使用超类。如果泛型破坏了下游的一切,那么重载可能是一条出路。你能告诉我你所说的重载是什么意思吗?比如在所有子类中重写方法?这是我在所有16个子类中都需要的一种方法,这就是为什么我想在我的超类中使用它,但按照这里的建议,解决了我提出的问题,破坏了其他一切。重写将不起作用,因为您无法更改返回类型。重载(相同的名称但不同的参数)只在您更改一种输入参数类型时起作用。所以你可能不得不这么做
new MyChildClass().SetBase().As<MyChildClass>().SetThis();
class Program
{
    static void Main(string[] args)
    {
        var obj = new MyClass();
        //obj.SetThis().SetThat().SetThisThirdThing().setThisFourthThing(); // Compile error
        obj.SetThis().SetThat().Cast<MyClass>().SetThisThirdThing().setThisFourthThing();
    }
}

class SuperClass
{
    public SuperClass SetThat()
    {
        return this;
    }

    public T Cast<T>() where T : SuperClass
    {
        return (T)this;
    }
}

class MyClass : SuperClass
{
    public MyClass SetThis()
    {
        return this;
    }

    public MyClass SetThisThirdThing()
    {
        return this;
    }

    public MyClass setThisFourthThing()
    {
        return this;
    }
}