Why C# Is Not Allowing Non-Member Functions Like C++

Why C# is not allowing non-member functions like C++

See this blog posting:

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

(...)

I am asked "why doesn't C# implement feature X?" all the time. The answer is always the same: because no one ever designed, specified, implemented, tested, documented and shipped that feature. All six of those things are necessary to make a feature happen. All of them cost huge amounts of time, effort and money. Features are not cheap, and we try very hard to make sure that we are only shipping those features which give the best possible benefits to our users given our constrained time, effort and money budgets.

I understand that such a general answer probably does not address the specific question.

In this particular case, the clear user benefit was in the past not large enough to justify the complications to the language which would ensue. By stricting how different language entities nest inside each other we (1) restrict legal programs to be in a common, easily understood style, and (2) make it possible to define "identifier lookup" rules which are comprehensible, specifiable, implementable, testable and documentable.

By restricting method bodies to always be inside a struct or class, we make it easier to reason about the meaning of an unqualified identifier used in an invocation context; such a thing is always an invocable member of the current type (or a base type).

(...)

and this follow-up posting:

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

(...)

Like all design decisions, when we're faced with a number of competing, compelling, valuable and noncompossible ideas, we've got to find a workable compromise. We don't do that except by considering all the possibilites, which is what we're doing in this case.

(emphasis from original text)

Why Not Use Public Member Functions

The more public your methods (and types) are, the more code they're exposed to. That increases the chance that other code (even code under your company's control) will start depending on that code working the way it currently does... which limits the flexibility to change the implementation later.

To give a concrete example, I'm working on an open source project called Noda Time. Now admittedly we haven't had our first public release yet, but I've recently been making a load of changes to various internal types - including changing the type hierarchies fairly significantly, and even removing methods. If those had been public types or public methods (and if we'd already gone to v1.0) then we could have broken code which depended on that specific implementation.

By hiding everything you don't know to be useful to clients, you buy yourself a lot of flexibility. It's incredibly important to put a lot of thought into your public API, because that's really hard to change later - but if you've kept a lot of your implementation internal, you can refactor to your heart's content to make it more elegant, more flexible, or perhaps faster... all without breaking any of the code depending on your library.

Obviously some things need to be exposed - at least in class libraries - but you should be careful just how much you expose, unless you're happy to break all callers later on (or live with every decision you make, forever).

Global vs. Member functions

Nope, there is only one instance. All instances of a class point to an object that contains all the instance methods that take an implicit first parameter affectionately called this. When you invoke an instance method on an instance the this pointer for that instance is passed as the first parameter to that method. That is how the method knows all the instance fields and properties for that instance.

For details see CLR via C#.

This is, of course, complicated by virtual methods. CLR via C# will spell out the distinction for you and is highly recommended if you are interested in this subject. Either way, there is still only one instance of each instance method. The issue is just how these methods are resolved.

Why cannot implicitly implement a non-public interface member?

Interface members don't have scopes like public or internal. What you have here is a default interface implementation.

So you need to remove the scope on the interface:

interface IMyInterface{
int Property {get; set;}
}

Functions in a namespace?

C# does not allow for free functons. Each function must reside in a type. This is just the way it works, it's not a matter of technical possibility, it was a design decision.

You may be interested in this article.


On a side note, ever notice how Intellisense works much, much better when writing C# than C++? This is one of those things that help (not the only one, but one).

EDIT: Funny, in reading that linked article I noticed that this is a dup...

Accessing a C++ non-member function from C# via reflection

No, it doesn't. You need to learn how C++/CLI works- you can't just recompile a C++ program with /CLR and be done with it. The sc_main method here is native, not managed, and you can't reflect over it, and the same is true about the HelloWorld type, unless you redefined it to be a ref class, but I doubt you did because there you go in main instantiating it by value, which would only be legal if it was a native class.

.NET and native code have very fundamentally different semantics and a magic compiler switch will not help you in this regard.

How can I store the address of a non member function in a DWORD (c++)

You should use a pointer rather than a DWORD. On the C# side IntPtr is probably fine. Perhaps a delegate would be better. Hard to tell for sure with no code.

On the C++ side you could use void* but better might be a properly typed function pointer:

typedef DWORD (__stdcall *ThreadProc)(void*);

Rather than defining this yourself you can use LPTHREAD_START_ROUTINE.

Any of these options will work for both 32 and 64 bit.

However, do note that the injected DLL must have the same bitness as the target process. You cannot inject 64 bit DLL into 32 bit process and vice versa. What's more you cannot inject into a 64 bit process by calling CreateRemoteThread from a 32 bit process.



Related Topics



Leave a reply



Submit