C#에서 추상 정적 메서드를 사용할 수 없는 이유는 무엇인가요?

최근에 공급자로 꽤 많이 작업하고 있는데, 추상 정적 메서드가 있는 추상 클래스를 갖고 싶은 흥미로운 상황에 직면했습니다. 이 주제에 대한 몇 개의 게시물을 읽었는데 어느 정도 이해가 되긴 했지만 명확한 설명이 있나요?

질문에 대한 의견 (6)
해결책

정적 메서드는 인스턴스화된 메서드가 아니며, 객체 참조 없이 사용할 수 있습니다.

정적 메서드 호출은 객체 참조가 아닌 클래스 이름을 통해 이루어지며, 이를 호출하는 중간 언어(IL) 코드는 추상 메서드를 정의한 클래스 이름을 통해 호출하며, 반드시 사용한 클래스 이름이 아니어도 호출할 수 있습니다.

예를 보여드리겠습니다.

다음 코드가 있습니다:

public class A
{
    public static void Test()
    {
    }
}

public class B : A
{
}

B.Test를 호출하면 다음과 같이 됩니다:

class Program
{
    static void Main(string[] args)
    {
        B.Test();
    }
}

그러면 Main 메서드 내부의 실제 코드는 다음과 같습니다:

.entrypoint
.maxstack 8
L0000: nop 
L0001: call void ConsoleApplication1.A::Test()
L0006: nop 
L0007: ret 

보시다시피, 코드를 그렇게 작성할 수 있음에도 불구하고 B.Test가 아닌 A 클래스가 정의했기 때문에 A.Test로 호출됩니다.

델파이에서처럼 객체가 아닌 유형을 참조하는 변수를 만들 수 있는 클래스 유형이 있다면 가상이므로 추상적인 정적 메서드(및 생성자도)를 더 많이 사용할 수 있겠지만, 사용할 수 없으므로 .NET에서는 정적 호출이 가상적이지 않습니다.

IL 설계자가 코드를 컴파일하여 B.Test를 호출하도록 허용하고 런타임에 호출을 확인할 수는 있지만 여전히 일종의 클래스 이름을 작성해야 하므로 여전히 가상이 아닙니다.

가상 메서드, 즉 추상 메서드는 런타임에 다양한 유형의 객체를 포함할 수 있는 변수를 사용할 때만 유용하며, 따라서 현재 변수에 있는 객체에 적합한 메서드를 호출하고 싶을 때만 유용합니다. 정적 메서드를 사용하면 어쨌든 클래스 이름을 거쳐야 하므로 호출할 정확한 메서드는 컴파일 시점에 알 수 있고 변경할 수도 없습니다.

따라서 가상/추상 정적 메서드는 .NET에서 사용할 수 없습니다.

해설 (3)

정적 메서드는 상속하거나 재정의할 수 없으므로 추상화할 수 없습니다. 정적 메서드는 클래스의 인스턴스가 아닌 유형에 정의되므로 해당 유형에서 명시적으로 호출해야 합니다. 따라서 자식 클래스에서 메서드를 호출하려면 해당 이름을 사용하여 호출해야 합니다. 이렇게 하면 상속이 무의미해집니다.

잠시 정적 메서드를 상속할 수 있다고 가정해 봅시다. 이 시나리오를 상상해 보세요:

public static class Base
{
    public static virtual int GetNumber() { return 5; }
}

public static class Child1 : Base
{
    public static override int GetNumber() { return 1; }
}

public static class Child2 : Base
{
    public static override int GetNumber() { return 2; }
}

Base.GetNumber()를 호출하면 어떤 메서드가 호출될까요? 어떤 값이 반환될까요? 객체의 인스턴스를 만들지 않으면 상속이 다소 어렵다는 것을 쉽게 알 수 있습니다. 상속이 없는 추상 메서드는 본체가 없는 메서드일 뿐이므로 호출할 수 없습니다.

해설 (5)

다른 객체에 대한 응답 (맥도웰) 할 수 있을 것이라고 다형성 때만 인스턴스입니다. 검증함 한다고 지적했다. 같이 가지 않는 언어 치료를 클래스뿐만 인스턴스입니다 &quot Class"; 또는 &quot Metaclass"; 유형:. 이러한 언어의 다형성 (정적) 및 클래스용 인스턴스입니다 못하며창조된 지원부에서는 모두 사용할 수 있습니다.

C #, Java, C++ 언어 등 전에 같은 것이 아닙니다. 이 아닌 '정적' 키워드를 사용할 수 있다는 이 방식은 정적으로 바인딩되지 명시적으로 동적임 /가상.

해설 (0)

앞선 설명에 추가하자면, 정적 메서드 호출은 컴파일 타임에 특정 메서드에 바인딩되므로 오히려 다형성 동작이 배제됩니다.

해설 (6)

이것은 정적 필드 및 메서드을 상속을 필요한 상황이 말해둘꼐요 있습니다.

abstract class Animal
{
  protected static string[] legs;

  static Animal() {
    legs=new string[0];
  }

  public static void printLegs()
  {
    foreach (string leg in legs) {
      print(leg);
    }
  }
}

class Human: Animal
{
  static Human() {
    legs=new string[] {"left leg", "right leg"};
  }
}

class Dog: Animal
{
  static Dog() {
    legs=new string[] {"left foreleg", "right foreleg", "left hindleg", "right hindleg"};
  }
}

public static void main() {
  Dog.printLegs();
  Human.printLegs();
}

//what is the output?
//does each subclass get its own copy of the array "legs"?
해설 (3)

실제로 정적임 오버라이드합니다 it& 조금 있지만, s ugly 서버리스 (의 델파이), # 39 의 작동하잖아 그냥 그랬다고 합니다.

우리가 사용하는 클래스는 클래스 인스턴스 없이 있을 수 있으므로, 예를 들어, 우리는 그들의 객체에는 바뀌엇어요 사용할 수 있는 방법은 다음과 같습니다.

class function AvailableObjects: string; override;
begin
  Result := 'Object1, Object2';
end; 

39 의 it& 있으나 반드시 필요한 것은 무엇인가, 그 대신 우리가 할 수 있기 때문에 이런 식으로 인스턴스화하지 요구되는가 린스탄티안테드 검색하는 데 사용할 수 있는 모든 클래스뿐만 그냥 객체에는.

그러나 이 는 간단한 예를 들어, 응용 프로그램 자체가 디스크입니다. diskid 사용할 수 있는 클래스는 모든 클라이언트-서버 애플리케이션 서버, 클라이언트 서버 한 수 있는 모든 일을 결코 할 필요가 있으며, 여러 개의 서로 다른 개체의 인스턴스입니다.

이 때문에 다른 것보다 훨씬 더 쉽게 유지할 수 있도록 한 서버 애플리케이션 각 클라이언트입니다.

예를 들어 분명히 있다.

해설 (0)

이 가상 메소드가 추상 상태이다. 그러나 정적 메서드는 메서드 가 필요 없는 추상적 인스턴스입니다 인스턴스입니다. 그래서, 추상 클래스, 그냥 就不可能拥有 포함될 수 있는 정적 메서드는 정적 추상 (추상 또는 정적).

해설 (1)