.Net: How to find unused Fields / DataMember in the class? - vb.net

I'm having more than 150 Datacontacts in each I've more than 10 DataMember. How to find the unused Datamember in the code?
I'm able to find by right-clicking on the DataMember and "Find All Reference" option, But this is not a solution to my problem because I’ve huge number of DataMember.
update :
I've find one Vs2010 plug-in Ndepend.Using this I'm able to find unused methods and classes but not DataMember.
I've tried below code in Ndepend but it is not working.
// <Name>Potentially dead Fields</Name>
warnif count > 0
from f in JustMyCode.Fields where
f.NbMethodsUsingMe == 0 &&
!f.IsPublic && // Although not recommended, public fields might be used by client applications of your assemblies.
!f.IsLiteral && // The IL code never explicitely uses literal fields.
!f.IsEnumValue && // The IL code never explicitely uses enumeration value.
f.Name != "value__" && // Field named 'value__' are relative to enumerations and the IL code never explicitely uses them.
!f.HasAttribute("NDepend.Attributes.IsNotDeadCodeAttribute".AllowNoMatch()) &&
!f.IsGeneratedByCompiler // If you don't want to link NDepend.API.dll, you can use your own IsNotDeadCodeAttribute and adapt this rule.
select f
screen :

I've removed the Property Key word in the DataMember.then I ran the Ndepend.
I'm able to find the unused Datamembers.
Public Class AccountInformation
<DataMember()>
Public Property AccountNumber As String
<DataMember()>
Public Property OtherElementQualifier As String
<DataMember()>
Public Property OtherElementNumber As String
End Class
remove Property Keyword
Public Class AccountInformation
<DataMember()>
Public AccountNumber As String
<DataMember()>
Public OtherElementQualifier As String
<DataMember()>
Public OtherElementNumber As String
End Class
then run the below script in Ndepend.
// <Name>Potentially dead Fields</Name>
warnif count > 0
from f in JustMyCode.Fields where
f.NbMethodsUsingMe == 0 &&
//!f.IsPublic && Although not recommended, public fields might be used by client applications of your assemblies.
!f.IsLiteral && // The IL code never explicitely uses literal fields.
!f.IsEnumValue && // The IL code never explicitely uses enumeration value.
f.Name != "value__" && // Field named 'value__' are relative to enumerations and the IL code never explicitely uses them.
!f.HasAttribute("NDepend.Attributes.IsNotDeadCodeAttribute".AllowNoMatch()) &&
!f.IsGeneratedByCompiler // If you don't want to link NDepend.API.dll, you can use your own IsNotDeadCodeAttribute and adapt this rule.
select f

Related

How can I detect when a ReadOnly property has accidentally been passed by reference?

I'm working on a project which is written in VB.NET. The project has several Structures which used to have writable fields. I replaced all of those fields with read-only properties, and wrote functions for creating a copy of a structure that has one of its properties changed.
I was assuming that every part of the code that attempted to write to one of these properties would become an error, and then I could simply fix all the errors by making the code call the new functions. To my dismay, it turns out that if a ReadOnly property is accidentally passed into a ByRef parameter of a function, the compiler accepts this with no warning, and the value that's assigned is silently discarded!
Here's an example:
Structure Point
Public ReadOnly Property X As Integer
Public ReadOnly Property Y As Integer
End Structure
Module Module1
Sub IncreaseByOne(ByRef x As Integer)
x = x + 1
End Sub
Sub Main()
Dim point As New Point
IncreaseByOne(point.X)
Console.WriteLine($"point.X is {point.X}")
End Sub
End Module
I was hoping that the line IncreaseByOne(point.X) would throw an error, or at least a warning, since point.X is read-only and it doesn't make sense to pass it by reference. Instead, the code compiles with no warnings, and the value assigned to x inside of IncreaseByOne is silently discarded, and the program prints point.X is 0.
How can I detect all of the places in my code where a read-only property is passed into a function that takes it by reference? The only way I can think of is to go through every read-only property that I have, find all places where that property is used as a parameter, and look to see if that parameter is ByRef. That'll be very time-consuming, but if there's no other solution, then that's what I'll do.
I'm using Visual Studio 2019. I'm open to installing new software in order to do this.
That's really interesting. The VB.NET Compiler really tries to make a property look like a variable. Even if I explicitly declare the property as
Structure Point
Dim _x As Integer
ReadOnly Property X() As Integer
Get
Return _x
End Get
End Property
End Structure
The code compiles and executes as before. If the property setter is added, it even works correctly!
Structure Point
Dim _x As Integer
Property X() As Integer
Get
Return _x
End Get
Set(value As Integer)
_x = value
End Set
End Property
End Structure
With the above change, the program correctly prints 1.
Looking at the generated IL, we can see why:
IL_0009: ldloca.s point
IL_000b: call instance int32 VisualBasicConsoleTest.Point::get_X()
IL_0010: stloc.1 // Store returned value in local variable
IL_0011: ldloca.s // load address of that local variable (and pass to function call)
IL_0013: call void VisualBasicConsoleTest.Program::IncreaseByOne(int32&)
IL_0018: nop
IL_0019: ldloca.s point
IL_001b: ldloc.1 // Load contents of local variable again
IL_001c: call instance void VisualBasicConsoleTest.Point::set_X(int32) // and call setter
Even though we expect an error because a property is not a value (and a byref requires a value), the compiler fakes what we might have intended: He actually generates a call to the getter, stores the value on the stack, passes a reference to the stack(!) to the called function and then calls the setter with that value.
This works in this simple scenario, but I agree with the commenters above, this might be very confusing when looking at it in detail. If the property is actually a computed property, the outcome is just arbitrary (try implementing the getter as Return _x + 1...)
C# would throw an error here, because a property is not a value and hence cannot be used as an out or ref parameter.
As Craig suggested in this answer, I went ahead and wrote a custom analyzer to detect when this occurs. Now, I can simply do Analyze / Run Code Analysis / On Solution, and every place that the described problem occurs gets marked with a warning such as "The property 'point.X' is read-only and should not be passed by reference."
The entire analyzer is available on GitHub. I've copied the important part below:
public override void Initialize(AnalysisContext context)
{
context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None);
context.EnableConcurrentExecution();
context.RegisterSyntaxNodeAction(AnalyzeSyntax, SyntaxKind.SimpleArgument);
}
private static void AnalyzeSyntax(SyntaxNodeAnalysisContext context)
{
SimpleArgumentSyntax node = (SimpleArgumentSyntax)context.Node;
SemanticModel semanticModel = context.SemanticModel;
if (!IsByRef(node, semanticModel))
return;
(bool isReadOnly, string symbolType) = IsReadOnly(node, semanticModel);
if (isReadOnly)
{
Diagnostic diagnostic = Diagnostic.Create(
Rule,
node.Expression.GetLocation(),
symbolType,
node.Expression.GetText());
context.ReportDiagnostic(diagnostic);
}
}
/// <summary>
/// Determine if the given argument is passed by reference.
/// </summary>
private static bool IsByRef(SimpleArgumentSyntax node, SemanticModel semanticModel)
{
ArgumentListSyntax argumentList = (ArgumentListSyntax)node.Parent;
if (argumentList.Parent is InvocationExpressionSyntax invocation)
{
SymbolInfo functionInfo = semanticModel.GetSymbolInfo(invocation.Expression);
if (functionInfo.Symbol is IMethodSymbol method)
{
IParameterSymbol thisParameter = null;
if (node.IsNamed)
{
thisParameter = method.Parameters.FirstOrDefault(parameter =>
parameter.Name == node.NameColonEquals.Name.ToString());
}
else
{
int thisArgumentIndex = argumentList.Arguments.IndexOf(node);
if (thisArgumentIndex < method.Parameters.Length)
thisParameter = method.Parameters[thisArgumentIndex];
}
// If we couldn't find the parameter for some reason, the
// best we can do is just accept it.
if (thisParameter == null)
return false;
RefKind refKind = thisParameter.RefKind;
if (refKind != RefKind.None && refKind != RefKind.In)
return true;
}
}
return false;
}
/// <summary>
/// Determine if the given argument is a read-only field or property.
/// </summary>
private static (bool isReadOnly, string symbolType) IsReadOnly(SimpleArgumentSyntax node, SemanticModel semanticModel)
{
string symbolType = "field or property";
bool isReadOnly = false;
if (node.Expression is MemberAccessExpressionSyntax memberAccess)
{
SymbolInfo memberInfo = semanticModel.GetSymbolInfo(memberAccess.Name);
if (memberInfo.Symbol is IPropertySymbol propertySymbol && propertySymbol.IsReadOnly)
{
symbolType = "property";
isReadOnly = true;
}
if (memberInfo.Symbol is IFieldSymbol fieldSymbol && fieldSymbol.IsReadOnly)
{
symbolType = "field";
isReadOnly = true;
}
}
return (isReadOnly, symbolType);
}
There isn't a way to catch this with the compiler. Even Option Strict On will allow passing a read-only property to a ByRef argument. This is defined to pass by copy-in/copy-out, and it's surprising to me that the copy-out part will compile even when the Property Set is inaccessible.
If you want to have an automated lint-type check for this, I would imagine that a custom analyzer could find it. I haven't worked with analyzers, so I don't have any specific suggestions for how to write one or set it up.
Otherwise, you're left to a manual check. As was noted in a comment, you can use the "Find All References" command from Visual Studio to help with it, but this will still require a manual review of every read-only property.

AOP - #Pointcut syntax: how define the method with a superclass argument/parameter

I am working with Spring Framework and AspectJ version 1.8.9
I have many Service classes, lets consider for example
CustomerServiceImpl
InvoiceServiceImpl
CarServiceImpl
The point is, each one has a saveOne method. Therefore
saveOne(Customer customer)
saveOne(Invoice invoice)
saveOne(Car car)
If I use the following:
#Pointcut(value="execution(* com.manuel.jordan.service.impl.*ServiceImpl.saveOne(Car, ..)) && args(entity) && target(object)")
public void saveOnePointcut(Car entity, Object object){}
#Before(value="ServicePointcut.saveOnePointcut(entity, object)")
public void beforeAdviceSaveOne(Car entity, Object object){
It works. Until here for a better understanding:
The first parameter represents the Entity (Car in this case) to persist
The second parameter represents the Object or target (XServiceImpl) has been 'intercepted'
Note: I need the first parameter for audit and logging purposes. Therefore it is mandatory.
To avoid do verbose and create more for each entity, I want use a 'superclass' type. I've tried with
#Pointcut(value="execution(* com.manuel.jordan.service.impl.*ServiceImpl.saveOne(Object, ..)) && args(entity) && target(object)")
public void saveOnePointcut(Object entity, Object object){}
#Before(value="ServicePointcut.saveOnePointcut(entity, object)")
public void beforeAdviceSaveOne(Object entity, Object object){
Observe the first parameter now is an Object And it does not work.
If is possible accomplish this requirement, what is the correct syntax?
I've read Clarification around Spring-AOP pointcuts and inheritance but it is about only for methods without parameter(s)
You can try to use Object+ instead of just Object. + means all classes that extend target class. So your aspect code will look like this:
#Pointcut(value="execution(* com.manuel.jordan.service.impl.*ServiceImpl.saveOne(Object+, ..)) && args(entity) && target(object)")
public void saveOnePointcut(Object entity, Object object){}
#Before(value="ServicePointcut.saveOnePointcut(entity, object)")
public void beforeAdviceSaveOne(Object entity, Object object){
I tried this with my code samples and it's work fine for all type of arguments.

Why is this Entity Framework association not loading lazily?

I'm using a Code First Entity Framework approach, and in my OnModelCreating function I have the following code:
With modelBuilder.Entity(Of FS_Item)()
.HasKey(Function(e) e.ItemKey)
.Property(Function(e) e.ItemRowVersion).IsConcurrencyToken()
.HasMany(Function(e) e.ItemInventories) _
.WithRequired(Function(e) e.Item).HasForeignKey(Function(e) e.ItemKey)
End With
Elsewhere I have a Web API Get implementation with some diagnostic code I'm looking at in a debugger:
Public Function GetValue(ByVal id As String) As FS_Item
GetValue = If(data.FS_Item.Where(Function(i) i.ItemNumber = id).SingleOrDefault(), New FS_Item())
Dim c = GetValue.ItemInventories.Count
End Function
I expect that c should get a non-zero value by looking up rows in the FS_Inventory view where ItemKey matches the retrieved FS_Item row's ItemKey. But I'm getting 0 even though there are matching rows. Am I calling .HasMany, .WithRequired and .HasForeignKey properly?
Note that .WithRequired is operating on the return value from the previous line whereas the other lines are operating on the With block expression.
Edit This model for FS_Item has been requested. Here it is:
Partial Public Class FS_Item
Public Property ItemNumber As String
Public Property ItemDescription As String
Public Property ItemUM As String
Public Property ItemRevision As String
Public Property MakeBuyCode As String
' Many many more properties
Public Property ItemRowVersion As Byte()
Public Property ItemKey As Integer
Private _ItemInventories As ICollection(Of FS_ItemInventory) = New HashSet(Of FS_ItemInventory)
Public Overridable Property ItemInventories As ICollection(Of FS_ItemInventory)
Get
Return _ItemInventories
End Get
Friend Set(value As ICollection(Of FS_ItemInventory))
_ItemInventories = value
End Set
End Property
End Class
Edit Learned something interesting. If I change Dim c = GetValue.ItemInventories.Count to this:
Dim c = data.FS_ItemInventory.ToList()
Dim correctCount = GetValue.ItemInventories.Count
Then correctCount gets the value of 3. It's like it understands the association between the objects, but not how to automatically query them as I'm used to coming from LINQ-to-SQL. Is EF different somehow in this regard?
Edit I have determined that I can make the associated objects load using this explicit loading code:
data.Entry(GetValue).Collection(Function(e) e.ItemInventories).Load()
What I want to understand now is what exactly determines whether an entity will load lazily or not? From all indications I can find, it should have loaded lazily. I even tried changing the declaration of ItemInventories to this, but then I got a NullReferenceException when trying to access it:
Public Overridable Property ItemInventories As ICollection(Of FS_ItemInventory)
It turns out that code which I thought was unrelated had disabled lazy loading. I have this in the constructor of FSDB:
DirectCast(Me, IObjectContextAdapter).ObjectContext.ContextOptions.ProxyCreationEnabled = False
Thanks to EF 4 - Lazy Loading Without Proxies I see that this will also disable lazy loading. The reason that code had been added was due to another error:
Type
'System.Data.Entity.DynamicProxies.FS_Item_64115A45C642902D6044AFA1AFD239E7DCB82FD000A10FE4F8DE6EA26A2AB418'
with data contract name
'FS_Item_64115A45C642902D6044AFA1AFD239E7DCB82FD000A10FE4F8DE6EA26A2AB418:http://schemas.datacontract.org/2004/07/System.Data.Entity.DynamicProxies'
is not expected. Consider using a DataContractResolver or add any
types not known statically to the list of known types - for example,
by using the KnownTypeAttribute attribute or by adding them to the
list of known types passed to DataContractSerializer.
And according to Serialization of Entity Framework objects with One to Many Relationship, the easy solution for that was to disable proxies.

VS2010's "Public Property <PropertyName> As <DataType> vs. Public var

In VS2008, I used to type
Public Property <PropName> As <dataType>
and hit the Enter key and the IDE editor would automatically expand it out to a full blown property block.
Now, from what I understand, a new feature of 2010 is that the compiler automatically "expands" the short syntax above into the same IL code that you would get with the full property GET AND SET sub methods that were are accustomed to seeing before in the editor.
But functionality, how the heck is this any different than just having a Public class level variable? If the only diff is what it compiles to and if otehrwise there is no functional difference, isn't the new way less efficient than the old since it involves more code than just having a class level memory variable?
Public <Variable> as <DataType>
I thought that if you weren't going to have code behind your properties that they were essentially the same. I guess the diffrenece is that they just added the keyword "Property" but functionality, their is no diff, eh?
It makes little difference in this particular case, but I never use Public data members - anything that needs exposing outside the class is always done with properties. This means a little more work when declaring them, but when later on you wish that you had a property / accessor methods because you need to implement some code, it's a lot easier knowing that everywhere else in the code is already using your property...
Before someone pulls me up on this, no - it's not the same anyhow... You could manipulate a public member using a reference for instance...
This heavily ties into why properties are useful. They provide a level of isolation between the class implementation and the client code that uses it. When you use a public field, you cannot easily refactor the way the field behaves, the client code references it directly. Changing the field to a property for example requires recompiling all client code that uses it.
The usefulness of an automatic property is that it doesn't force you to decide up front that a field may need to be refactored some day. You can postpone the decision and change it from an automatic property to an explicit property with custom behavior any time you like. Without having to make any changes in the client code.
The JIT compiler ensures that an automatic property is just as efficient as a field, it inlines the accessor method call. The new automatic property syntax makes it just as efficient on your wrists as a public field. This is a complete win-win, it just doesn't make any sense anymore to ever use a public field again.
I am not sure, if I understand your question correctly.
But the need of a public class level variable vs property is already discussed here.
EDIT: Also, the IDE/Compiler makes it easy for you to reduce the code, if you are simply doing get/set
e.g.
public string Name { get; set; }, which doesn't require you to declare a backing field.
But then,you will have to access this member (even inside the class) using the property. Because, the compiler generates a backing field for you & the name of it is unknown.
One other difference is that properties are accessed from other controls such as DataGridView, that can read public property values but not variables.
The major difference between Auto-Implemented Properties (VB) and public Fields are interface definitions.
Codes that are using your class with Auto-Implemented Properties does not need to change if in the future you decide to add logic to the property, whereas if you're using fields you will have to modify the interface definition to a property.
So Auto-Implemented Properties uses the simple syntax of a public Field (without the full blown property declaration) but with the flexibility of a property.
A little bit of example:
Current code (C#):
class PersonA {
public int Age;
public int BirthYear;
}
class PersonB {
public int Age { get; set; }
public int BirthYear { get; set; }
}
Usage:
var john = new PersonA { Age = 30, BirthYear = 1980 };
var jane = new PersonB { Age = 20, BirthYear = 1990 };
If in the future you decide to scrap Age setter and derive the value from BirthYear, you can easily update your class without breaking any of the current client code.
class PersonA {
public int Age { get { return Date.Now.Year - BirthYear; }; set { } };
public int BirthYear;
}
class PersonB {
public int Age { get { return Date.Now.Year - BirthYear; }; set { } };
public int BirthYear { get; set; }
}
Usage:
var john = new PersonA { Age = 30, BirthYear = 1980 }; // broken when not recompiled
var jane = new PersonB { Age = 20, BirthYear = 1990 };

Weird VB.NET array-property situation

I have this weird situation.
I have these two classes:
Public Class Entry
End Class
Public Class Core
End Class
One of the properties of the Core class will be an array of Entry objects. How can I declare it?
Now, the only way to change (add/remove) this array from outside should be using two functions - AddEntry(Ent As Entry) and RemoveEntry(ID As String). Note that here, whoever is calling the AddEntry function should only be bothered with creating an Entry object and passing it. It will be added to the existing array.
But, the Entry array should be accessible like this from outside, for looping through and printing or whatever like this:
' core1 is a valid Core object
For Each Ent As Entry In core1.Entries
MsgBox(Ent.SomeProperty)
Next Ent
Is it possible to expose the Array as a property but restrict modification through functions alone? I know that the logic inside the Add and Remove functions can be inside the setter or getter, but the person wanting to add should pass only a single Entry object.
It is like saying You have readonly access to the array, but for modifying it, just create an object and send it or the ID to remove it. Don't bother about the entire array.
I hope I am making sense.
Why do you want to expose it as an array ?
What I would do, is use a List internally to store the entries. (That List would be private)
Create the necessary public methods (AddEntry / RemoveEntry / ... ), which manipulate the private list.
Then, create a public property which exposes the List, but in a ReadOnly fashion. That is, that property should return an ReadOnlyCollection instance.
Like this:
(I know it is in C#, but that 's my 'main language' - a bit too lazy to convert it to VB.NET)
public class Core
{
private List<Entry> _entries = new List<Entry>();
public void AddEntry( Entry entry )
{
_entries.Add (entry);
}
public ReadOnlyCollection<Entry> Entries
{
get { return _entries.AsReadOnly(); }
}
}
EDIT: VB.Net version provided by MarkJ
Imports System.Collections.ObjectModel
Public Class Core
Private _entries As New List(Of Entry)
Public Sub AddEntry( new As Entry )
_entries.Add (new)
End Sub
Public ReadOnly Property Entries() As ReadOnlyCollection(Of Entry)
Get
Return _entries.AsReadOnly
End Get
End Property
End Class
Create a private field for the array and then create your accessing methods to work with the array internally. In order to expose this array to callers so that they can enumerate it you should expose a property of type IEnumerable(Of T).
This approach is not foolproof, however as a clever caller could simply cast the IEnumerable(Of T) back to an array and modify it so it may be necessary to create a copy of the array and return that as the IEnumerable(Of T). All this has obvious performance penalties as I am sure you already see. This is just one of many issues that can arise when arrays are used as underlying data structures.
You can keep the List private and instead return an IEnumerable. Code generated via Reflector - I hope it's readable:
Public Class Core
Public Sub AddEntry(ByVal Ent As Entry)
Me.entries.Add(Ent)
End Sub
Public Sub RemoveEntry(ByVal ID As String)
Dim pred As Predicate(Of Entry) = Function (ByVal entry As Entry)
Return (entry.Id = ID)
End Function
Me.entries.RemoveAll(pred)
End Sub
Public ReadOnly Property Entries As IEnumerable(Of Entry)
Get
Return Me.entries
End Get
End Property
Private entries As List(Of Entry) = New List(Of Entry)
End Class
Note: I'd recommend using a List<Entry> instead of an array if you'll be adding and removing objects - or perhaps even a Dictionary<string, Entry> given the way you are using it.