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

C# 如何使用通用基类实现服务定位器模式?

C# 如何使用通用基类实现服务定位器模式?,c#,generics,C#,Generics,我陷入了困境,似乎找不到出路。我试图实现一个简单的[Service Locator][1],由下面示例代码中的GetInstance方法表示。现在的问题是,我在return语句中得到一个编译器错误,它说: 无法将类型“Cyberspace.SubClass”隐式转换为“Cyberspace.BaseClass” 我尝试过重写,这样子类本身就是一个泛型类,但是在DoSomething方法中的return语句中出现了编译器错误 有人能让这段代码编译,保留服务定位器模式原则吗?这些原则允许我在getI

我陷入了困境,似乎找不到出路。我试图实现一个简单的[Service Locator][1],由下面示例代码中的GetInstance方法表示。现在的问题是,我在return语句中得到一个编译器错误,它说:

无法将类型“Cyberspace.SubClass”隐式转换为“Cyberspace.BaseClass”

我尝试过重写,这样子类本身就是一个泛型类,但是在DoSomething方法中的return语句中出现了编译器错误

有人能让这段代码编译,保留服务定位器模式原则吗?这些原则允许我在getInstance方法中有一个抽象的返回类型?还是我想在这里做些不可能的事

namespace Cyberspace
{
    class BaseClass<T>
    {
        BaseClass<T> GetInstance() 
        { 
            return new SubClass();
        }
        virtual T DoSomething() { return default(T); }          
    }

    class SubClass : BaseClass<OtherClass>
    {
        public override OtherClass DoSomething()
        { 
            var other = new OtherClass { Description = "Generics are hard"};
            return other;
        }
    }

    class OtherClass
    {
        internal string Description { get; set; }
    }
}
命名空间网络空间
{
类基类
{
基类GetInstance()
{ 
返回新的子类();
}
虚拟T DoSomething(){返回默认值(T);}
}
类子类:基类
{
公共覆盖其他类DoSomething()
{ 
var other=new OtherClass{Description=“泛型是硬的”};
归还他人;
}
}
另一类
{
内部字符串说明{get;set;}
}
}
尝试2:

namespace Cyberspace
{
    class BaseClass<T>
    {
        static BaseClass<T> GetInstance() // The "Service Locator" method
        { 
            return new SubClass<T>(); 
        }
        internal virtual T DoSomething() { return default(T); }        
    }

    class SubClass<T> : BaseClass<T> where T: OtherClass
    {
        internal override T DoSomething()
        { 
            var other = new OtherClass { Description = "Generics are hard"};
            return (T) other;
        }
    }

    class OtherClass
    {
        internal string Description { get; set; }
    }
}
命名空间网络空间
{
类基类
{
静态基类GetInstance()//服务定位器方法
{ 
返回新的子类();
}
内部虚拟T DoSomething(){返回默认值(T);}
}
类子类:基类,其中T:OtherClass
{
内部超控T剂量测定法()
{ 
var other=new OtherClass{Description=“泛型是硬的”};
返回(T)其他;
}
}
另一类
{
内部字符串说明{get;set;}
}
}
这会在第
行返回新的子类()时产生以下错误:


类型“T”不能用作泛型类型或方法“Cyberspace.SubClass”中的类型参数“T”。没有从“T”到“Cyberspace.OtherClass”的装箱转换或类型参数转换

我不清楚您真正想做什么,但我可以告诉您为什么会发生编译错误

此方法返回的任何内容:

BaseClass GetInstance()


必须能够处理任何类型
T
(因为您没有类型约束)<代码>子类
只能处理一种类型,不能处理所有类型。因此,您不能返回它。

当使用类型参数
t
时,您声明:“我不关心实际的类型是什么。我只需要一些类型,任何类型。称它为
t
”。但在你的情况下,看起来你想要一个特定的类型。那么,就不需要泛型了

class SubClass : BaseClass<OtherClass>
{
    internal override OtherClass DoSomething()
    { 
        var other = new OtherClass { Description = "Generics are hard"};
        return other;
    }
}
因为
T
可能来自
OtherClass
。不能将
OtherClass
转换为从
OtherClass
派生的类。没有意义,而且编译器足够聪明,可以捕捉到它


评论中的讨论导致以下解决方法:

return (BaseClass<T>)(object)new SubClass();
返回(基类)(对象)新的子类();

当然,只有当类型在运行时对齐时,这才有效。

有几个选项。最简单的方法是将
基类GetInstance()
更改为
基类GetInstance()
。更复杂的方法是让子类是泛型的和/或通过
where
子句强制约束泛型类型。更改为BaseClass GetInstance()会将该方法仅锁定到该特定类。我想要一个通用的方法。我也考虑过使用where约束使子类泛型,但这会在DoSomething方法()中产生问题。看起来我需要一个特定的类型,因为示例仅使用“OtherClass”实例化它。然而,在实际应用程序中实例化时,我将使用其他类而不是OtherClass(双关语)。为什么在子类上需要一个类型参数T?哦,我明白了-我想你的意思也是基类。不,对于子类我不需要它,但是基类将不会编译-参见第一个代码示例。GetInstance实现没有意义,因为您承诺能够提供任何类型t,但您只能提供不同的子类。由于不完全了解您的意图,这里有一个解决方法:
return(BaseClass)(object)new SubClass()当然,这只在类型在运行时排列的情况下有效。如果您将该变通方法作为答案发布(或将其嵌入现有答案),我会将其标记为正确答案。它起作用了——我很高兴!:-)至于我的意图,如果你检查我在GitHub发布的这个改进版本,并提供更好的命名和解释,也许它们会更清楚:
return (BaseClass<T>)(object)new SubClass();