Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/305.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#_Oop_Generics_Interface_Abstract Class - Fatal编程技术网

C# 访问从泛型抽象基派生的类中重写的抽象属性所需的接口?

C# 访问从泛型抽象基派生的类中重写的抽象属性所需的接口?,c#,oop,generics,interface,abstract-class,C#,Oop,Generics,Interface,Abstract Class,因此,我的困境是,为了从UtilityThing访问IntThing或StringThing的MyProperty,我定义了一个MyProperty接口,并将其用作UtilityThing中T的通用约束。这是可行的,但考虑到抽象库中已经定义了相同的属性,这似乎是多余的。我是否遗漏了设计的一个方面,或者这实际上是在这个例子中需要完成的方式 public interface IThing { string MyProperty { get; set; } } public abstrac

因此,我的困境是,为了从
UtilityThing
访问
IntThing
StringThing
MyProperty
,我定义了一个
MyProperty
接口,并将其用作
UtilityThing
T
的通用约束。这是可行的,但考虑到抽象库中已经定义了相同的属性,这似乎是多余的。我是否遗漏了设计的一个方面,或者这实际上是在这个例子中需要完成的方式

public interface IThing {
    string MyProperty { get; set; } 
}

public abstract class Thing<T> {
    protected string _MyProperty;
    public abstract string MyProperty { get; set; }
    public T OtherProperty { get; set; }

    public string CommonMethod() {
        return MyProperty + "foobar";   
    }
}

public class IntThing : Thing<int?>, IThing {
    public override string MyProperty {
        get { return _MyProperty; }
        set { _MyProperty = value + OtherProperty.ToString(); }
    }
}

public class StringThing: Thing<string>, IThing {
    public override string MyProperty {
        get { return _MyProperty; }
        set { _MyProperty = OtherProperty + value; }
    }
}

public class UtilityThing<T> where T: IThing, new() {
    public T DoIt(SomeContext someContext, string name) {
        string contextVal = someContext.GetValue(name);

        var thing = new T { MyProperty = contextVal }
        return thing;
    }
}
public接口信息{
字符串MyProperty{get;set;}
}
公共抽象类事物{
受保护的字符串\u MyProperty;
公共抽象字符串MyProperty{get;set;}
公共T其他属性{get;set;}
公共字符串CommonMethod(){
返回MyProperty+“foobar”;
}
}
公共类IntThing:Thing,IThing{
公共重写字符串MyProperty{
获取{return\u MyProperty;}
设置{u MyProperty=value+OtherProperty.ToString();}
}
}
公共类StringThing:Thing{
公共重写字符串MyProperty{
获取{return\u MyProperty;}
设置{u MyProperty=OtherProperty+value;}
}
}
公共类实用程序thing,其中T:IThing,new(){
公共T DoIt(SomeContext SomeContext,字符串名){
字符串contextVal=someContext.GetValue(名称);
var thing=newt{MyProperty=contextVal}
归还物;
}
}

您需要引入新的泛型类型。一旦引入了新类型,就可以消除对接口的需求

public class UtilityThing<T, I> where T : Thing<I>, new()
{
    public T DoIt(SomeContext someContext, string name)
    {
        string contextVal = someContext.GetValue(name);

        var thing = new T { MyProperty = contextVal };
        return thing;
    }
}
公共类实用程序Thing,其中T:Thing,new()
{
公共T DoIt(SomeContext SomeContext,字符串名)
{
字符串contextVal=someContext.GetValue(名称);
var thing=newt{MyProperty=contextVal};
归还物;
}
}
您可以这样使用它:

var utility = new UtilityThing<IntThing, int?>();
var utility=new UtilityThing();

但是
东西是抽象的,不能实例化。@BrettRossier你不是在实例化抽象类,你是在实例化具体的IntThing或StringThing,你只是说t必须从抽象类派生。我已经编辑了我的responseHmm,这是可行的,但它本质上将冗余转移到了
实用程序的通用参数中。另外,由于
IntThing
Thing
之间缺乏可兑换性,示例的原始使用部分可能会失败(
IntThing
东西,而不是
东西)。我希望避免这种用法,尽管它会在编译时被捕获。如果C#根据约束进行更多的类型推断,那就太好了
UtilityThing
将推断约束
中所需的类型,其中T:Thing
@BrettRossier-类型推断已经是编译器中最复杂的部分之一,有时会导致指数复杂性。为了简化实现,他们决定要么全部推断,要么什么都不推断。如果要指定一种类型,则必须指定所有类型。当然,对于不提供附带的非泛型工厂类的类(而不是方法),你根本没有推论。我已经更新了我的答案)通常的方法是引入另一个抽象类
Thing
,它包含
Thing
的非泛型成员,然后让
Thing
派生自
Thing
@Damien\u不信者你会移动哪些成员?MyProperty实现依赖于OtherProperty;),我希望它保持抽象,以便派生类需要它的实现。