我正在使用.NET框架,我真的希望能够创建一个我所有网站都使用的自定义类型的页面.当我尝试从控件访问页面时出现问题.我希望能够返回我的特定类型的页面而不是默认页面.有没有办法做到这一点?
public class MyPage : Page
{
// My own logic
}
public class MyControl : Control
{
public MyPage Page { get; set; }
}
Run Code Online (Sandbox Code Playgroud) 下面的代码是实现协变返回类型的唯一方法吗?
public abstract class BaseApplication<T> {
public T Employee{ get; set; }
}
public class Application : BaseApplication<ExistingEmployee> {}
public class NewApplication : BaseApplication<NewEmployee> {}
Run Code Online (Sandbox Code Playgroud)
我希望能够构造一个Application或NewApplication并让它从Employee属性返回适当的Employee类型.
var app = new Application();
var employee = app.Employee; // this should be of type ExistingEmployee
Run Code Online (Sandbox Code Playgroud)
我相信这段代码工作得很好,但是当我有几个需要相同行为的属性时,它变得非常讨厌.
有没有其他方法来实现这种行为?泛型或其他?
我想知道为什么泛型类型参数的新约束只能在没有参数的情况下应用,也就是说,可以将类型约束为具有无参数构造函数,但是不能将类约束为具有构造函数,接收一个int作为参数.我知道这方面的方法,使用反射或工厂模式,工作正常,好吧.但我真的很想知道为什么,因为我一直在思考它,我真的想不出无参数构造函数和带有参数的区别,这些参数可以证明对新约束的这种限制.我错过了什么?非常感谢
@Eric:让我和你在一起一会儿:
构造函数是方法
那么我想如果我这样做,没有人会反对:
public interface IReallyWonderful
{
new(int a);
string WonderMethod(int a);
}
Run Code Online (Sandbox Code Playgroud)
但是一旦我有了,那我就去:
public class MyClass<T>
where T : IReallyWonderful
{
public string MyMethod(int a, int b)
{
T myT = new T(a);
return myT.WonderMethod(b);
}
}
Run Code Online (Sandbox Code Playgroud)
这首先是我想要做的.所以,抱歉,但不,构造函数不是方法,或者至少不完全.
关于实现这个功能的困难,我真的不知道,即使我这样做了,我对于明智地支出股东资金的决定也没什么可说的.这样的话,我会马上把它标记为答案.
从学术(我)的角度来看,也就是说,没有任何关于实施成本的问题,问题确实是(我在最近几个小时内完成了这个问题):
构造函数应该被视为类的实现的一部分,还是作为语义契约的一部分(以同样的方式将接口视为语义契约).
如果我们将构造函数视为实现的一部分,那么,约束泛型类型参数的构造函数不是一件非常通用的事情,因为这会将你的泛型类型绑定到具体的实现,并且几乎可以说为什么完全使用泛型?
作为实现的一部分的构造函数的示例(在指定任何下面的构造函数作为定义的语义契约的一部分时没有意义ITransformer):
public interface ITransformer
{
//Operates with a and returns the result;
int Transform(int a);
}
public class PlusOneTransformer : ITransformer
{
public int Transform(int a)
{
return a …Run Code Online (Sandbox Code Playgroud) 拿这个小LINQPad示例:
void Main()
{
Foo<object> foo = new Foo<string>();
Console.WriteLine(foo.Get());
}
class Foo<out T>
{
public T Get()
{
return default(T);
}
}
Run Code Online (Sandbox Code Playgroud)
它无法使用此错误进行编译:
方差修饰符无效.只能将接口和委托类型参数指定为变量.
我没有看到代码的任何逻辑问题.一切都可以静态验证.为什么不允许这样做?它是否会导致语言不一致,或者由于CLR的限制而被认为实施起来太昂贵了?如果是后者,我作为开发人员应该知道什么是上述限制?
考虑到接口支持它,我希望从逻辑上遵循该类支持.
我正在阅读Codehua at Work中对Joshua Bloch的采访,他在Java 5中对泛型的介绍感到遗憾.他不喜欢具体的实现,主要是因为方差支持--Java的通配符 - 使得它不必要地复杂化.
据我所知,C#3没有像明确的,有界的通配符那样的东西,例如你不能声明一个接收Asset或任何Asset子类(void PriceBatch(Collection<? extends Asset> assets)在Java中?)的方法PriceBatch .
有谁知道为什么没有将通配符和边界添加到C#中?故意遗漏这些功能以使语言更简单,或者这是他们还没有实现的东西呢?
编辑:圣烟,Eric Lippert本人的评论!在阅读了他和Paul的深刻见解之后,我意识到至少支持上限,并且上面的例子可以转换为C#:
void PriceBatch<T>(ICollection<T> assets) where T : Asset
Run Code Online (Sandbox Code Playgroud)
另一方面,显然不支持下限,因为Eric在他的第二条评论中说,例如,可能没有办法直接将这个(有点人为的)Java代码转换为C#:
public class Asset {}
public class Derivative extends Asset {}
public class VanillaOption extends Derivative {}
public static <T extends Asset> void copyAssets(Collection<T> src, Collection<? super T> dst) {
for(T asset : src) dst.add(asset);
}
Collection<VanillaOption> src = new ArrayList<VanillaOption>();
[...]
Collection<Derivative> dst = new ArrayList<Derivative>();
[...]
copyAssets(src, dst);
Run Code Online (Sandbox Code Playgroud)
我对么?如果是这种情况,C#有上限而不是下限的特殊原因是什么?
协方差(大致)是在使用它们的复杂类型中镜像 "简单"类型的继承的能力.
例如,我们总是可以将一个实例Cat视为一个实例Animal.如果ComplexType是协变ComplexType<Cat>的ComplexType<Animal>,则可以将A 视为a .
我想知道:协方差的"类型"是什么,它们与C#有什么关系(它们是否受支持?)
代码示例会有所帮助.
例如,一种类型是返回类型协方差,由Java支持,但不支持C#.
我希望有功能编程印章的人也可以加入!