質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.49%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Visual Studio 2010

Microsoft Visual Studio 2010はMicrosoftが提供している統合開発環境(IDE)です。

VB.NET

Microsoft Visual Basic .NETのことで、Microsoft Visual Basic(VB6)の後継。 .NET環境向けのプログラムを開発することができます。 現在のVB.NETでは、.NET Frameworkを利用して開発を行うことが可能です。

Q&A

解決済

1回答

3599閲覧

VB.NETのAttributeUsage属性が期待した動作をしない

arisuke

総合スコア13

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Visual Studio 2010

Microsoft Visual Studio 2010はMicrosoftが提供している統合開発環境(IDE)です。

VB.NET

Microsoft Visual Basic .NETのことで、Microsoft Visual Basic(VB6)の後継。 .NET環境向けのプログラムを開発することができます。 現在のVB.NETでは、.NET Frameworkを利用して開発を行うことが可能です。

0グッド

0クリップ

投稿2018/03/12 12:54

編集2018/03/12 13:50

お世話になります。

前提・実現したいこと

現在、属性を利用したプログラムをVB.NETで作成しています。
特に問題なくできたと思っていたのですが、以下のような問題が生じ、期待した動作(属性を継承しない)を実現できません。

発生している問題

AttributeUsage属性のInherited引数をfalseに設定しているが、継承先で属性がそのまま継承されている。

該当のソースコード

簡略化したソースコードを載せておきます。

<AttributeUsage(AttributeTargets.Property, Inherited:=False)> Public Class IdAttribute Inherits Attribute End Class Public Class Parent <Id()> Public Property parentId As Integer End Class Public Class Child Inherits Parent <Id()> Public Property childId As Integer End Class Module Module1 Sub Main() Console.WriteLine("Parent") Dim parent As New Parent For Each propInfo In parent.GetType().GetProperties() If propInfo.IsDefined(GetType(IdAttribute), False) Then Console.WriteLine("inherited: " & propInfo.Name) End If Next Console.WriteLine("") Console.WriteLine("Child") Dim child As New Child For Each propInfo In child.GetType().GetProperties() If propInfo.IsDefined(GetType(IdAttribute), False) Then Console.WriteLine("inherited: " & propInfo.Name) End If Next End Sub End Module

上記を実行すると
Parent
inherited: parentId

Child
inherited:childId
inherited:parentId ←属性が継承されている
と表示されます。マニュアルのAttributeUsageなどを見た限り、ChiledクラスではparentIdは表示されないように思えます。

試したこと

同様にC#でも試してみた結果、C#では期待した動作をします。(ChildクラスでparentIdが表示されない)

C#のソースコードも載せておきます。

[AttributeUsage(AttributeTargets.Property, Inherited = false)] public class IdAttribute : Attribute { } public class Parent { [Id] public int parentId { get; set; } } public class Child { [Id] public int childId { get; set; } } class Program { static void Main(string[] args) { Console.WriteLine("Parent"); var parent = new Parent(); foreach (var propInfo in parent.GetType().GetProperties()) { if (propInfo.IsDefined(typeof(IdAttribute), false)) { Console.WriteLine("inherited: " + propInfo.Name); } } Console.WriteLine("Child"); var child = new Child(); foreach (var propInfo in child.GetType().GetProperties()) { if (propInfo.IsDefined(typeof(IdAttribute), false)) { Console.WriteLine("inherited: " + propInfo.Name); }; } } }

上記を実行すると
Parent
inherited: parentId

Child
inherited: childId
と表示されます。

補足情報(FW/ツールのバージョンなど)

環境は
Windows7
VisualStudio2010
TargetFrameWork 4.0
です。

また以下の環境でも現象を確認しております。
windows7
VisualStudio2017
TargetFrameWork 4.5.2

個人的には最初バグかな?と思ったのですが、調べてみてもそういった情報が出てこないので、なにか勘違いをしているのかなと思っています。(が、わからない。プロパティ関連でなにか勘違いしているのでしょうか?)
もしなにか知っておられたら教えて頂けないでしょうか?
よろしくお願いします。

追記:C#のコードの方でChildクラスがPanretクラスを継承していませんでした。
継承した結果、VB.NETと同じ結果となりました。
ということはそもそもこういう動作になるのが正常ということなのでしょうか?

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

C#

1using System; 2 3namespace ConsoleApp1 4{ 5 [AttributeUsage(AttributeTargets.Property, Inherited = false)] 6 public class IdAttribute : Attribute 7 { 8 } 9 10 [AttributeUsage(AttributeTargets.Property, Inherited = true)] 11 public class InheritableIdAttribute : Attribute 12 { 13 } 14 15 class Parent 16 { 17 [Id] 18 [InheritableId] 19 public virtual int Id { get; set; } 20 21 [Id] 22 [InheritableId] 23 public virtual int Id2 { get; set; } 24 } 25 26 class Child : Parent 27 { 28 public override int Id { get; set; } 29 } 30 31 class Program 32 { 33 static void Main(string[] args) 34 { 35 PrintAttributes(typeof(Parent), "Id"); 36 PrintAttributes(typeof(Parent), "Id2"); 37 PrintAttributes(typeof(Child), "Id"); 38 PrintAttributes(typeof(Child), "Id2"); 39 Console.ReadKey(); 40 } 41 42 static void PrintAttributes(Type type, string propertyName) 43 { 44 foreach (var attribute in Attribute.GetCustomAttributes(type.GetProperty(propertyName))) 45 { 46 Console.WriteLine($"{type}.{propertyName}: {attribute}"); 47 } 48 } 49 } 50}

出力

ConsoleApp1.Parent.Id: ConsoleApp1.IdAttribute ConsoleApp1.Parent.Id: ConsoleApp1.InheritableIdAttribute ConsoleApp1.Parent.Id2: ConsoleApp1.IdAttribute ConsoleApp1.Parent.Id2: ConsoleApp1.InheritableIdAttribute ConsoleApp1.Child.Id: ConsoleApp1.InheritableIdAttribute ConsoleApp1.Child.Id2: ConsoleApp1.IdAttribute ConsoleApp1.Child.Id2: ConsoleApp1.InheritableIdAttribute

こんな感じになります。
Parent を継承した Child のオーバーライドされたメソッドで IdAttribute が消えています。

投稿2018/03/12 15:15

Zuishin

総合スコア28660

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

arisuke

2018/03/12 21:01

なるほど、あくまでオーバーライドした場合に限ると。 手元のほうでも確認できました。 ありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.49%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問