Programing

C #이 C ++와 같은 비 멤버 함수를 허용하지 않는 이유

lottogame 2020. 11. 17. 07:37
반응형

C #이 C ++와 같은 비 멤버 함수를 허용하지 않는 이유


C #에서는 멤버가 아닌 함수를 작성할 수 없으며 모든 메서드는 클래스의 일부 여야합니다. 나는 이것을 모든 CLI 언어의 제한으로 생각했습니다. 그러나 나는 틀렸고 C ++ / CLI가 비 멤버 함수를 지원한다는 것을 알았습니다. 컴파일 될 때 컴파일러는 메서드를 명명되지 않은 클래스의 멤버로 만듭니다.

다음은 C ++ / CLI 표준이 말하는 것입니다.

[참고 : 비 멤버 함수는 CLI에서 명명되지 않은 클래스의 멤버로 취급됩니다. 그러나 C ++ / CLI 소스 코드에서 이러한 함수는 해당 클래스 이름으로 명시 적으로 규정 될 수 없습니다. 끝 참고]

메타 데이터에서 비 멤버 함수의 인코딩은 지정되지 않습니다. [참고 : 이러한 기능은 공개적으로 표시 될 수 없기 때문에 interop 문제가 발생하지 않습니다. 끝 참고]

그래서 내 질문은 왜 C #이 이와 같은 것을 구현하지 않는 것입니까? 아니면 멤버가 아닌 함수가 있어서는 안되며 모든 메소드가 어떤 클래스에 속해야한다고 생각하십니까?

내 의견은 비 멤버 함수 지원을 갖는 것이며 클래스의 인터페이스를 오염시키는 것을 방지하는 데 도움이됩니다.

이견있는 사람..?


이 블로그 게시물을 참조하십시오.

http://blogs.msdn.com/ericlippert/archive/2009/06/22/why-doesn-tc-implement-top-level-methods.aspx

(...)

"C #에서 기능 X를 구현하지 않는 이유는 무엇입니까?"라는 질문을 받았습니다. 항상. 대답은 항상 동일합니다. 아무도 해당 기능을 설계, 지정, 구현, 테스트, 문서화 및 제공하지 않았기 때문입니다. 기능을 구현하려면이 여섯 가지가 모두 필요합니다. 그들 모두는 엄청난 시간과 노력과 돈이 들었습니다. 기능은 저렴하지 않으며 제한된 시간, 노력 및 비용 예산을 감안할 때 사용자에게 최상의 이점을 제공하는 기능 만 제공하도록 노력하고 있습니다.

나는 그러한 일반적인 대답이 아마도 특정 질문을 다루지 않는다는 것을 이해합니다.

이 특별한 경우에, 명확한 사용자 혜택은 과거에 발생할 언어의 복잡성을 정당화하기에 충분하지 않았습니다. 서로 다른 언어 엔터티가 서로 중첩되는 방식을 제한함으로써 (1) 합법적 프로그램이 공통되고 이해하기 쉬운 스타일로 제한되고 (2) 이해 가능하고 지정 가능하며 구현 가능하고 테스트 가능한 "식별자 조회"규칙을 정의 할 수 있습니다. 문서화 할 수 있습니다.

메서드 본문이 항상 구조체 또는 클래스 내부에 있도록 제한함으로써 호출 컨텍스트에서 사용되는 규정되지 않은 식별자의 의미를 쉽게 추론 할 수 있습니다. 그런 것은 항상 현재 유형 (또는 기본 유형)의 호출 가능한 멤버입니다.

(...)

그리고이 후속 게시물 :

http://blogs.msdn.com/ericlippert/archive/2009/06/24/it-already-is-a-scripting-language.aspx

(...)

모든 디자인 결정과 마찬가지로 우리는 경쟁적이고, 설득력 있고, 가치 있고, 불가능한 아이디어에 직면했을 때 실행 가능한 타협점을 찾아야합니다. 모든 가능성고려 하는 것 외에는 그렇게하지 않습니다 .이 경우에 우리가하는 일입니다.

(원문 강조)


Java에서 허용하지 않았기 때문에 C #에서는 허용하지 않습니다.

Java 디자이너가 허용하지 않은 몇 가지 이유를 생각할 수 있습니다.

  • Java는 단순하도록 설계되었습니다. 그들은 임의의 단축키가없는 언어를 만들려고했기 때문에 일반적으로 다른 접근 방식이 더 깨끗하거나 더 간결하더라도 모든 작업을 수행 할 수있는 한 가지 간단한 방법 만 있습니다. 그들은 학습 곡선을 최소화하기를 원했고 "클래스는 메소드를 포함 할 수있다"를 배우는 것이 "클래스는 메소드를 포함 할 수 있고 함수는 클래스 외부에 존재할 수있다"보다 더 간단합니다.
  • 표면적으로는 덜 객체 지향적으로 보입니다. (객체의 일부가 아닌 것은 분명히 객체 지향이 될 수 없습니까? 그럴 수 있습니까? 물론 C ++는 예라고 말하지만 C ++는이 결정에 관여하지 않았습니다)

이미 코멘트에서 말했듯이 이것은 좋은 질문이라고 생각하며 비회원 기능이 선호되는 경우가 많이 있습니다. (이 부분은 대부분 "필요하지 않다"라는 다른 모든 답변에 대한 응답입니다.)

비 멤버 함수가 허용되는 C ++에서는 여러 가지 이유로 선호되는 경우가 많습니다.

  • 캡슐화를 돕습니다. 클래스의 private 멤버에 액세스 할 수있는 메서드가 적을수록 클래스가 리팩토링하거나 유지 관리하기가 더 쉽습니다. 캡슐화는 OOP의 중요한 부분입니다.
  • 코드는 클래스의 일부가 아닐 때 훨씬 쉽게 재사용 할 수 있습니다. 예를 들어, C ++ 표준 라이브러리는 std::find또는 std :: sort`를 비 멤버 함수로 정의 하므로 배열, 집합, 연결 목록 또는 (std :: find, at의 경우) 모든 유형의 시퀀스에서 재사용 할 수 있습니다. 최소한) 스트림. 코드 재사용도 OOP의 중요한 부분입니다.
  • 더 나은 디커플링을 제공합니다. find기능은 작업 할 수 있기 위해 LinkedList의 클래스에 대해 알 필요가 없다. 멤버 함수로 정의 된 경우 LinkedList 클래스의 멤버가되며 기본적으로 두 개념을 하나의 큰 Blob으로 병합합니다.
  • 확장 성. 클래스의 인터페이스가 "모든 공용 멤버"가 아니라 "클래스에서 작동하는 모든 비 멤버 함수"라는 것을 수락하면 편집하거나 편집 할 필요없이 클래스의 인터페이스를 확장 할 수 있습니다. 클래스 자체를 다시 컴파일하십시오.

멤버가 아닌 함수를 가질 수있는 기능은 C (다른 선택의 여지가 없음)에서 시작되었을 수 있지만, 현대 C ++에서는 이전 버전과의 호환성을위한 것이 아니라 더 간단한 이유 때문에 그 자체로 중요한 기능입니다. , 더 깨끗하고 재사용 가능한 코드를 허용합니다.

사실 C #은 훨씬 나중에 동일한 것을 실현 한 것 같습니다. 확장 방법이 추가 된 이유는 무엇입니까? 단순한 Java와 유사한 구문을 유지하면서 위의 목표를 달성하려는 시도입니다. Lambda는 또한 본질적으로 특정 클래스의 구성원이 아니라 자유롭게 정의되는 작은 함수이기 때문에 흥미로운 예입니다. 그렇습니다. 비 멤버 함수의 개념이 유용하며 C #의 디자이너도 같은 것을 깨달았습니다. 그들은 단지 뒷문을 통해 개념을 몰래 들어 가려고 시도했습니다.

http://www.ddj.com/cpp/184401197http://www.gotw.ca/publications/mill02.htm 은이 주제에 대해 C ++ 전문가가 작성한 두 개의 기사입니다.


비 멤버 함수는 캡슐화를 개선 하고 유형 간의 결합을 줄 이므로 좋은 것 입니다. Haskell 및 F #과 같은 대부분의 최신 프로그래밍 언어는 무료 기능을 지원합니다.


명명 된 클래스에 각 메서드를 넣지 않는 이점은 무엇입니까 ? 멤버가 아닌 함수가 클래스의 인터페이스를 "오염"시키는 이유는 무엇입니까? 클래스의 공용 API의 일부로 사용하지 않으려면 공용으로 만들지 않거나 해당 클래스에 넣지 마십시오. 언제든지 다른 클래스를 만들 수 있습니다.

물론 익명 함수 외에는 적절한 범위없이 떠 다니는 메서드를 작성하고 싶었던 기억이 없습니다 (실제로 동일하지 않음).

요컨대 멤버가 아닌 함수에서 어떤 이점도 볼 수 없지만 모든 메서드를 적절하게 이름이 지정된 클래스에 넣을 때 일관성, 이름 지정 및 문서화 측면에서 이점을 볼 수 있습니다.


CLS (공용 언어 사양)에서는 CLS를 준수하는 라이브러리에 비 구성원 함수가 없어야한다고 말합니다. CLI (공용 언어 인터페이스)의 기본 제한에 추가 된 추가 제한과 같습니다.

향후 버전의 C # using에서는 클래스 이름 제한없이 클래스의 정적 멤버에 액세스 할 수 있도록 하는 지시문 을 작성하는 기능을 추가 할 수 있습니다.

using System.Linq.Enumerable; // Enumerable is a static class

...

IEnumerable<int> range = Range(1, 10); // finds Enumerable.Range

그러면 CLS 및 기존 라이브러리를 변경할 필요가 없습니다.

이 블로그 게시물 은 C #의 함수형 프로그래밍을위한 라이브러리보여 주며, 정적 메서드 호출을 한정하기위한 요구 사항으로 인해 발생하는 노이즈를 줄이기 위해 한 글자로 된 클래스 이름을 사용합니다. using지시어가 클래스를 대상으로 할 수 있다면 이와 같은 예는 조금 더 멋지게 만들어 질 것 입니다.


  • 모든 코드가 클래스 내에 있으면보다 강력한 리플렉션 기능 집합이 가능합니다.
  • 클래스 내에서 정적 메서드에 필요한 데이터를 초기화 할 수있는 정적 intializer를 사용할 수 있습니다.
  • 다른 컴파일 단위에서 추가 할 수없는 단위 내에 명시 적으로 포함하여 메서드 간의 이름 충돌을 방지합니다.

Since Java, most programmers have easily accepted that any method is a member of a class. I doesn't make any considerable obstacles and make the concept of method more narrow, which make a language easier.

However, indeed, class infers object, and object infers state, so the concept of class containing only static methods looks a little absurd.


I think you really need to clarify what you would want to create non-member static methods to achieve.

For instance, some of the things you might want them for could be handled with Extension Methods

Another typical use (of a class which only contains static methods) is in a library. In this case, there is little harm in creating a class in an assembly which is entirely composed of static methods. It keeps them together, avoids naming collisions. After all, there are static methods in Math which serve the same purpose.

Also, you should not necessarily compare C++'s object model with C#. C++ is largely (but not perfectly) compatible with C, which didn't have a class system at all - so C++ had to support this programming idiom out of the C legacy, not for any particular design imperative.


Bear something in mind: C++ is a much more complicated language than C#. And although they may be similiar syntactically, they are very different beasts semantically. You wouldn't think it would be terribly difficult to make a change like this, but I could see how it could be. ANTLR has a good wiki page called What makes a language problem hard? that's good to consult for questions like this. In this case:

Context sensitive lexer? You can't decide what vocabulay symbol to match unless you know what kind of sentence you are parsing.

Now instead of just worrying about functions defined in classes, we have to worry about functions defined outside classes. Conceptually, there isn't much difference. But in terms of lexing and parsing the code, now you have the added problem of having to say "if a function is outside a class, it belongs to this unnamed class. However, if it is inside the class, then it belongs to that class."

Also, if the compiler comes across a method like this:

public void Foo()
{
    Bar();
}

...it now has to answer the question "is Bar located within this class or is it a global class?"

Forward or external references? I.e., multiple passes needed? Pascal has a "forward" reference to handle intra-file procedure references, but references to procedures in other files via the USES clauses etc... require special handling.

This is another thing that causes problems. Remember that C# doesn't require forward declarations. The compiler will make one pass just to determine what classes are named and what functions those classes contain. Now you have to worry about finding classes and functions where functions can be either inside or outside of a class. This is something a C++ parser doesn't have to worry about as it parses everything in order.

Now don't get me wrong, it could probably be done in C#, and I would probably use such a feature. But is it really worth all the trouble of overcoming these obstacles when you could just type a class name in front of a static method?


Free functions are very useful if you combine them with duck typing. The whole C++ STL is based on it. Hence I am sure that C# will introduce free functions when they manage to add true generics.

Like economics, language design is also about psychology. If you create appetite for true generics via free functions in C# and not deliver, then you would kill C#. Then all C# developers would move to C++ and nobody wants that to happen, not the C# community and most certainly not those invested in C++.


While it's true you need a class (e.g. a static class called FreeFunctions) to hold such functions, you're free to place using static FreeFunctions; at the top of any file that needs the functions from it, without having to litter your code with FreeFunctions. qualifiers. I'm not sure if there's actually a case where this is demonstrably inferior to not requiring the function definitions to be contained in a class.


If you think about it, the counter argument would be "why doesn't C++ support extension methods" and the answer lies within their design goals.

C++ gives you namespace functions that you can call on any object which would help you "extending" that object in some way.

Most of the times I used namespace functions in C++ were to create functions that accept objects and do functionality that I don't want to put inside a class member function.

In C# you can create an extension method that does the job for you (most of the time). For what's left of the cases you will miss that feature.

Take the following code for example:

template<typename T>
unsigned int findCount(vector<T>& vec, T data){
    unsigned int count = 0;
    for(auto val : vec)
        if(val == data) ++count;
    return count;
}

Now if I needed that functionality for some purpose in my class, I can just add it to the class's namespace and use it without "polluting" my class with that function.

In C# you can achieve the same goal with extension method:

static class Extensions {
    public static uint FindCount<T>(this List<T> list, T data) {
        uint counts = 0;
        foreach (var item in list)
            if (item.Equals(data)) ++counts;
        return counts;
    }
}

And both of them work the same way which is cool. Many will argue about C++ missing extension methods, many will argue about C# missing namespace functions.

I think the best way to put it is by not comparing these languages to some detail because they are different languages with different implementations.

As you quoted in your question, C++/CLI does not "really" support namespace member functions since it adds an unnamed class to use them which is by no way close to C++ implementation, maybe close in the way it looks, but really different.

In the end, functionality is always something to look forward to, and as much as I want namespace member functions in C# is as much as I want extension methods in C++. Which isn't much anyway.

참고URL : https://stackoverflow.com/questions/1024171/why-c-sharp-is-not-allowing-non-member-functions-like-c

반응형