我真的需要这样的事情:
interface IReadableVar
{
object Value { get; }
}
interface IWritableVar
{
object Value { set; }
}
interface IReadableWritableVar : IReadableVar, IWritableVar
{
}
但是当我尝试使用IReadableWritableVar.Value
时,除非我明确地转换为基接口,否则我会收到编译错误,如下所示:
static void Main()
{
IReadableWritableVar var = null;
var t = var.Value; // <-- CS0229: Ambiguity between 'IReadableVar.Value' and 'IWritableVar.Value'
var.Value = null; // <-- CS0229: Ambiguity between 'IReadableVar.Value' and 'IWritableVar.Value'
var v = ((IReadableVar)var).Value; // compiles fine
((IWritableVar)var).Value = null; // compiles fine
}
为什么我会得到这些错误,尽管编译器应该清楚一切?除了强制转换(应用程序中有数百个位置)之外,还有什么方法可以解决这个问题吗?
更新:有人认为这是Implementing 2 Interfaces with 'Same Name' Properties的欺骗,但这有点不同,因为在另一种情况下,接口中没有继承。无论如何,问题现在已经解决了 - 见接受的答案。
答案 0 :(得分:15)
可能的解决方法是修改您的界面IReadableWritableVar
,如下所示:
interface IReadableWritableVar : IReadableVar, IWritableVar
{
new object Value { get; set; }
}
但请保持我的有效实施应该是:
class ReadableWritableVar : IReadableWritableVar
{
public object Value
{
get { throw new NotImplementedException(); }
set { throw new NotImplementedException(); }
}
object IWritableVar.Value
{
set { throw new NotImplementedException(); }
}
object IReadableVar.Value
{
get { throw new NotImplementedException(); }
}
}
更具体的例子:
class ReadableWritableVar : IReadableWritableVar
{
public object Value
{
get { return ((IReadableVar)this).Value; }
set { ((IWritableVar)this).Value = value; }
}
object _val;
object IWritableVar.Value { set { _val = value; } }
object IReadableVar.Value => _val;
}
甚至更好:
class ReadableWritableVar : IReadableWritableVar
{
public object Value { get; set; }
object IWritableVar.Value { set { Value = value; } }
object IReadableVar.Value => Value;
}
答案 1 :(得分:7)
有趣的问题。我认为扩展方法在这种情况下会有所帮助。
public static class Extension
{
public static object GetValue(this IReadableVar v)
{
return v.Value;
}
public static void SetValue(this IWritableVar v, object value)
{
v.Value = value;
}
}
您需要更改代码才能使用它:
IReadableWritableVar variable = null;
var t = variable.GetValue();
variable.SetValue(null);
扩展方法为你做演员。
答案 2 :(得分:2)
嗯,有效的Getter和Setter只是两种方法。当我们使用IReadableWritableVar
接口时,有两个方法具有从基接口继承的相同名称,并且编译器不知道它应该使用哪两个因此存在歧义。
当我们将其转换为其中一个接口时,其他成员已经消失,并且没有错误。
如果我们实现那些成员将没有错误,因为编译器将使用该实现:
class ReadableWritableVar : IReadableWritableVar
{
public object Value { get; set; }
}
var @var = new ReadableWritableVar();
var t = @var.Value;
如果要求你使用接口而不是类,你可以使用来自@Alessandro D'Andria的答案的显式接口成员实现。
答案 3 :(得分:0)
使用抽象类而不是接口将解决您的问题。
public abstract class ReadableWritableVar : IReadableVar, IWritableVar
{
public object Value { get; set; }
}
答案 4 :(得分:0)
一种可能的替代方法是使用显式(java风格)get和set方法而不是属性:
static void Main(string[] args)
{
IReadableWritableVar aVar = null;
var t = aVar.GetValue();
aVar.SetValue(null);
}
然后用法变为:
// send image to Twitter first
$url = 'https://upload.twitter.com/1.1/media/upload.json';
$requestMethod = 'POST';
$image = 'full/path/to/image.jpg';
$postfields = array(
'media_data' => base64_encode(file_get_contents($image))
);
$response = $twitter->buildOauth($url, $requestMethod)
->setPostfields($postfields)
->performRequest();
// get the media_id from the API return
$media_id = json_decode($response)->media_id;
// then send the Tweet along with the media ID
$url = 'https://api.twitter.com/1.1/statuses/update.json';
$requestMethod = 'POST';
$postfields = array(
'status' => 'My amazing tweet'
'media_ids' => $media_id,
);
$response = $twitter->buildOauth($url, $requestMethod)
->setPostfields($postfields)
->performRequest();