C #은 반환 형식 공분산을 지원합니까?
저는 .NET 프레임 워크로 작업하고 있으며 모든 웹 사이트에서 사용하는 사용자 지정 유형의 페이지를 만들고 싶습니다. 컨트롤에서 페이지에 액세스하려고 할 때 문제가 발생합니다. 기본 페이지 대신 특정 유형의 페이지를 반환하고 싶습니다. 이것을 할 방법이 있습니까?
public class MyPage : Page
{
// My own logic
}
public class MyControl : Control
{
public MyPage Page { get; set; }
}
원하는 것은 반환 유형 공분산처럼 들립니다. C #은 반환 형식 공분산을 지원하지 않습니다.
반환 유형 공분산은 덜 구체적인 유형을 반환하는 기본 클래스 메서드를보다 구체적인 유형을 반환하는 유형으로 재정의하는 곳입니다.
abstract class Enclosure
{
public abstract Animal Contents();
}
class Aquarium : Enclosure
{
public override Fish Contents() { ... }
}
Enclosure를 통한 콘텐츠 소비자는 동물을 기대하고 Aquarium은 그 요구 사항을 충족 할뿐만 아니라 동물은 항상 물고기라는 더 엄격한 약속을 약속하기 때문에 안전합니다.
이러한 종류의 공분산은 C #에서 지원되지 않으며 지원되지 않을 것입니다. CLR에서 지원하지 않습니다. (C ++ 및 CLR의 C ++ / CLI 구현에 의해 지원됩니다. 아래에서 제안하는 것과 같은 마법의 도우미 메서드를 생성하여 지원합니다.)
(일부 언어는 형식 매개 변수 유형 반 변성도 지원합니다. 즉, Animal을 취하는 메소드로 Fish를 취하는 메소드를 재정의 할 수 있습니다. 다시 말하지만, 계약이 이행됩니다. 기본 클래스는 모든 Fish를 처리해야하며 클래스는 물고기뿐만 아니라 모든 동물을 처리 할 것을 약속합니다. 마찬가지로 C # 및 CLR은 형식 매개 변수 유형 반 변성을 지원하지 않습니다.)
이 제한을 해결할 수있는 방법은 다음과 같이하는 것입니다.
abstract class Enclosure
{
protected abstract Animal GetContents();
public Animal Contents() { return this.GetContents(); }
}
class Aquarium : Enclosure
{
protected override Animal GetContents() { return this.Contents(); }
public new Fish Contents() { ... }
}
이제 가상 메서드를 재정의하는 이점과 컴파일 타임 유형의 Aquarium을 사용할 때 더 강력한 타이핑을 얻을 수 있습니다.
인터페이스를 사용하여 인터페이스를 명시 적으로 구현하여 해결했습니다.
public interface IFoo {
IBar Bar { get; }
}
public class Foo : IFoo {
Bar Bar { get; set; }
IBar IFoo.Bar => Bar;
}
이 블로그 게시물 시리즈에서는 반환 유형 공분산 문제에 대해 자세히 설명하고 IL로 수행하는 방법에 대해서도 설명합니다.
http://www.simple-talk.com/community/blogs/simonc/archive/2010/07/14/93495.aspx
http://www.simple-talk.com/community/blogs/simonc/archive/2010/07/16/93516.aspx
http://www.simple-talk.com/community/blogs/simonc/archive/2010/07/19/93562.aspx
링크를 게시하는 것만으로도 미안하지만 매우 상세하며 여기에서 스 니펫을 인용하는 것은 그다지 도움이되지 않습니다. IL 코드를 사용하여 달성 할 수있는 방법을 보여줍니다.
이것을 MyControl 개체에 배치하면 작동합니다.
public new MyPage Page {get return (MyPage)Page; set;}'
다른 유형을 반환하기 때문에 속성을 재정의 할 수 없지만 재정의 할 수 있습니다.
이 예에서는 비교적 간단하기 때문에 공분산이 필요하지 않습니다. 에서 기본 개체 Page
를 상속하는 것뿐입니다 MyPage
. 모든 Control
반환 할 것을 MyPage
대신 Page
요구는 재정의 할 수 Page
의 속성을Control
예, 공분산을 지원하지만 달성하려는 정확한 것에 따라 다릅니다.
나는 또한 제네릭을 많이 사용하는 경향이 있습니다. 즉, 다음과 같은 작업을 할 때 의미합니다.
class X<T> {
T doSomething() {
}
}
class Y : X<Y> {
Y doSomethingElse() {
}
}
var Y y = new Y();
y = y.doSomething().doSomethingElse();
그리고 당신의 유형을 "잃지"않는 것.
나는 그것을 시도하지 않았지만 작동하지 않습니까?
YourPageType myPage = (YourPageType)yourControl.Page;
예. 이를 수행하는 방법에는 여러 가지가 있으며 이는 하나의 옵션 일뿐입니다.
You can make your page implement some custom interface that exposes a method called "GetContext" or something, and it returns your specific information. Then your control can simply request the page and cast:
var myContextPage = this.Page as IMyContextGetter;
if(myContextPage != null)
var myContext = myContextPage.GetContext();
Then you can use that context however you wish.
You can access your page from any control by walking up the parent tree. That is
myParent = this;
while(myParent.parent != null)
myParent = myParent.parent;
*Did not compile or test.
Or get the parent page in the current context (depends on your version).
Then what I like to do is this: I create an interface with the functions I want to use in the control (for example IHostingPage)
Then I cast the parent page 'IHostingPage host = (IHostingPage)Parent;' and I am all set to call the function on the page I need from my control.
I will do it in this way:
class R {
public int A { get; set; }
}
class R1: R {
public int B { get; set; }
}
class A
{
public R X { get; set; }
}
class B : A
{
private R1 _x;
public new R1 X { get => _x; set { ((A)this).X = value; _x = value; } }
}
참고URL : https://stackoverflow.com/questions/5709034/does-c-sharp-support-return-type-covariance
'developer tip' 카테고리의 다른 글
memcached가 어떤 일을하고 있는지 어떻게 알 수 있습니까? (0) | 2020.10.21 |
---|---|
JVM에서 JIT 컴파일 된 코드를 보는 방법은 무엇입니까? (0) | 2020.10.21 |
System.Drawing.Color 값 설정 (0) | 2020.10.21 |
Moq, SetupGet, Mocking a property (0) | 2020.10.21 |
SQL-varchar 데이터 유형을 datetime 데이터 유형으로 변환하여 값이 범위를 벗어났습니다. (0) | 2020.10.21 |