??? MethodInfo Props are Wrong (or Docs are Wrong) ???


A

Alan Foxmore

Hi everyone,

I hope you can comment on this -- I'm pretty darned sure that either
some of the MethodInfo properties are wrong or the Microsoft
documentation is wrong.

Please have a look at the program below. It attempts to print out the
accessibility (i.e., "visibility") of each method in the class. I've
included the program along with its output.

The Microsoft documentation for MethodInfo tells us that the IsAssembly
property "Gets a value indicating whether this method can be called by
other classes in the same assembly." Okay, great. Public methods can
certainly be called from other classes in the same assembly, right? Not
according to the program below. The output indicates a public method
cannot be called from other classes within its assembly because the
IsAssembly property is false.

There are other inconsistencies in the output as well - for example, an
internal method cannot be called from a subclass in the same assembly.

Read the Microsoft documentation very carefully. You'll see that the
IsPrivate and IsPublic properties refer to the accessibility of the
member itself. For example, m.IsPublic indicates whether or not m is
public.

In contrast, IsFamily, IsAssembly, IsFamilyAndAssembly and
IsFamilyOrAssembly indicate whether the method in question can be
called from a method with that accessibility. For example, m.IsAssembly
indicates whether m can "be called by other classes in the same
assembly". This is distinctly different from saying that m has internal
accessibility. So, certainly any public method can "be called by other
classes in the same assembly", right? Not according to the output
below.

It's very inconsistent and the property values are inconsistent with
what the documentation says they should be.

I guess you can look at this as either the MethodInfo properties are
wrong or the Microsoft documentation is wrong. I guess I'm just a
stickler.

---------------------
using System;
using System.Reflection;

class Program {
private static void Main(string[] args) {
Type t = typeof(Program);
MemberInfo[] members = t.GetMembers(BindingFlags.Public |
BindingFlags.Instance |
BindingFlags.NonPublic |
BindingFlags.DeclaredOnly);

foreach (MemberInfo mi in members) {
Console.WriteLine(mi);
MethodInfo methodInfo = mi as MethodInfo;
if (methodInfo != null) {
Console.WriteLine(" Private: " + methodInfo.IsPrivate);
Console.WriteLine(" Public: " + methodInfo.IsPublic);
Console.WriteLine(" Assm: " + methodInfo.IsAssembly);
Console.WriteLine(" Fam: " + methodInfo.IsFamily);
Console.WriteLine(" Fam & Assm: " +
methodInfo.IsFamilyAndAssembly);
Console.WriteLine(" Fam | Assm: " +
methodInfo.IsFamilyOrAssembly);
}
Console.WriteLine();
}
} // main()

protected void ProtMethod() {}

internal void InternalMethod() {}

public void PublicMethod() {}

protected internal void ProtInternalMethod() {}
} // Program()

------ OUTPUT ----------
Void ProtMethod()
Private: False
Public: False
Assm: False
Fam: True
Fam & Assm: False
Fam | Assm: False

Void InternalMethod()
Private: False
Public: False
Assm: True
Fam: False
Fam & Assm: False
Fam | Assm: False

Void PublicMethod()
Private: False
Public: True
Assm: False
Fam: False
Fam & Assm: False
Fam | Assm: False

Void ProtInternalMethod()
Private: False
Public: False
Assm: False
Fam: False
Fam & Assm: False
Fam | Assm: True

Void .ctor()
 
Ad

Advertisements

N

Nick Hounsome

IMHO MS documentation is invariably poor but I can't think of a single
reason why you would want the behaviour shown.

To make matters even more confusing MethodAttributes is a Flags enum and has
values for both FamORAssem and FamANSAssem.

I did my own test program and got:

MyInternal IsFamily is False Attributes are PrivateScope, Assembly,
HideBySig

MyProtected IsFamily is True Attributes are PrivateScope, Family, HideBySig

MyProtectedInternal IsFamily is False Attributes are PrivateScope,
FamORAssem, HideBySig

MethodAttributes.ReuseSlot = 0x0000
MethodAttributes.PrivateScope = 0x0000
MethodAttributes.Private = 0x0001
MethodAttributes.FamANDAssem = 0x0002
MethodAttributes.Assembly = 0x0003
MethodAttributes.Family = 0x0004
MethodAttributes.FamORAssem = 0x0005
MethodAttributes.Public = 0x0006

Perversely we can see that Public is defined as "Family | FamANDAssem"
which clearly defies all reason!

There are a lot of enumerations in .NET that I think are a mess -
BindingFlags is another.


Alan Foxmore said:
Hi everyone,

I hope you can comment on this -- I'm pretty darned sure that either some
of the MethodInfo properties are wrong or the Microsoft documentation is
wrong.

Please have a look at the program below. It attempts to print out the
accessibility (i.e., "visibility") of each method in the class. I've
included the program along with its output.

The Microsoft documentation for MethodInfo tells us that the IsAssembly
property "Gets a value indicating whether this method can be called by
other classes in the same assembly." Okay, great. Public methods can
certainly be called from other classes in the same assembly, right? Not
according to the program below. The output indicates a public method
cannot be called from other classes within its assembly because the
IsAssembly property is false.

There are other inconsistencies in the output as well - for example, an
internal method cannot be called from a subclass in the same assembly.

Read the Microsoft documentation very carefully. You'll see that the
IsPrivate and IsPublic properties refer to the accessibility of the member
itself. For example, m.IsPublic indicates whether or not m is public.

In contrast, IsFamily, IsAssembly, IsFamilyAndAssembly and
IsFamilyOrAssembly indicate whether the method in question can be called
from a method with that accessibility. For example, m.IsAssembly indicates
whether m can "be called by other classes in the same assembly". This is
distinctly different from saying that m has internal accessibility. So,
certainly any public method can "be called by other classes in the same
assembly", right? Not according to the output below.

It's very inconsistent and the property values are inconsistent with what
the documentation says they should be.

I guess you can look at this as either the MethodInfo properties are wrong
or the Microsoft documentation is wrong. I guess I'm just a stickler.

---------------------
using System;
using System.Reflection;

class Program {
private static void Main(string[] args) {
Type t = typeof(Program);
MemberInfo[] members = t.GetMembers(BindingFlags.Public |
BindingFlags.Instance |
BindingFlags.NonPublic |
BindingFlags.DeclaredOnly);

foreach (MemberInfo mi in members) {
Console.WriteLine(mi);
MethodInfo methodInfo = mi as MethodInfo;
if (methodInfo != null) {
Console.WriteLine(" Private: " + methodInfo.IsPrivate);
Console.WriteLine(" Public: " + methodInfo.IsPublic);
Console.WriteLine(" Assm: " + methodInfo.IsAssembly);
Console.WriteLine(" Fam: " + methodInfo.IsFamily);
Console.WriteLine(" Fam & Assm: " +
methodInfo.IsFamilyAndAssembly);
Console.WriteLine(" Fam | Assm: " +
methodInfo.IsFamilyOrAssembly);
}
Console.WriteLine();
}
} // main()

protected void ProtMethod() {}

internal void InternalMethod() {}

public void PublicMethod() {}

protected internal void ProtInternalMethod() {}
} // Program()

------ OUTPUT ----------
Void ProtMethod()
Private: False
Public: False
Assm: False
Fam: True
Fam & Assm: False
Fam | Assm: False

Void InternalMethod()
Private: False
Public: False
Assm: True
Fam: False
Fam & Assm: False
Fam | Assm: False

Void PublicMethod()
Private: False
Public: True
Assm: False
Fam: False
Fam & Assm: False
Fam | Assm: False

Void ProtInternalMethod()
Private: False
Public: False
Assm: False
Fam: False
Fam & Assm: False
Fam | Assm: True

Void .ctor()
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top