2009-03-18 1 views
70

Используя Resharper 4.1, я столкнулся с этим интересным предупреждением: «Доступ к статическому члену типа через производный тип». Вот пример кода, где это происходит:Использование статического члена класса в производном типе?

class A { 
    public static void SomethingStatic() { 
     //[do that thing you do...] 
    } 
} 

class B : A { 
} 

class SampleUsage { 
    public static void Usage() { 
     B.SomethingStatic(); // <-- Resharper warning occurs here 
    } 
} 

Кто-нибудь знает, какие проблемы есть (если таковой имеется), делая использование статических членов страны А через B?

ответ

80

Одно из мест, где это может вводить в заблуждение, - это когда статический метод является заводским. класс WebRequest имеет фабричный метод Create, который позволяет записывать этот тип кода при доступе через производный класс.

var request = (FtpWebRequest)HttpWebRequest.Create("ftp://ftp.example.com"); 

Здесь request имеет тип FtpWebRequest, но это заблуждение, потому что это выглядит, как он был создан из HttpWebRequest (класс родственный), даже если метод Create фактически определяется на WebRequest (базовый класс). Следующий код идентичен по смыслу, но понятнее:

var request = (FtpWebRequest)WebRequest.Create("ftp://ftp.example.com"); 

В конце концов, нет никаких серьезных проблем доступа к статическому с помощью производного типа, но код часто яснее не делать этого.

+0

Это вопрос, о котором я никогда не думал. Спасибо, Грег! – Swim

+0

хорошее и ясное объяснение с хорошим примером. – serg10

+0

отличное объяснение, это было действительно полезно. Первый результат в google тоже ^^ – marcgg

15

Это не предупреждение, как правило, просто предложение. Вы создаете зависимость от чего-то ненужного.

Предположим, что позже вы решите, что B не нужно наследовать A. Если вы будете следовать совету Resharper, вам не нужно будет изменять эту строку кода.

+1

у вас будет такая же проблема с методами экземпляра. По всей этой логике, зачем наследовать что-нибудь? или я что-то упускаю? – NullVoxPopuli

+0

@NullVoxPopuli - Есть те, кто рекомендует избегать реализации наследования вообще. Несколько популярных книг на Java и C# предлагают это (см. Также этот документ: http://www.isase.us/wisr3/7.pdf). Но в любом случае, если у вас есть метод экземпляра 'Foo' в' A', тогда заданный экземпляр 'B', называемый переменной' b', вы не имеете такой же свободы, как в статическом случае, скажем, «где» Foo следует искать. Вы должны начать с 'b', что бы вы ни делали. Так что это не то же самое, что со статикой. –

2

Да, я тоже это видел, я всегда думал, что это просто предупреждает меня, потому что это не нужно. A.SomethingStatic(); будет делать то же самое.

29

B.SomethingStatic() делает заявление, что SomethingStatic является членом B. Это неправда. SomethingStatic является однозначно членом A. Тот факт, что он недоступен для неквалифицированных членов B (как если бы он был членом B), является вопросом удобства. Тот факт, что он доступен, когда он квалифицирован с B, является ИМО, ошибкой.

+2

+1 imo, ваше объяснение здесь самое лучшее. –

+0

Я думаю, что подкласс всегда должен наследовать каждое свойство суперкласса. Специально для проекта, на котором я сейчас, это очень полезно с заводскими шаблонами. – NullVoxPopuli

+0

Я не согласен. У меня есть действующий случай, когда текущее поведение выгодно.Вот идея: 'class Validator: ValidatorBase {}'. Использование: 'Validator.CheckNonEmpty (str)'. Сравните это с 'ValidatorBase .CheckNonEmpty (str)'. – Gebb